Anda di halaman 1dari 23

Nama : Garis Sanubari

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.

II. Landasan Teori


1. Kecerdasan Buatan
Artificial Intelligence (AI) atau kecerdasan buatan merupakan cabang dari ilmu
komputer yang berhubungan dengan pengautomatisasian tingkah laku cerdas.
Pernyataan tersebut juga dapat dijadikan definisi dari AI. Definisi ini menunjukkan
bahwa AI adalah bagian dari komputer sehingga harus didasarkan pada sound
theoretical (teori suara) dan prinsip-prinsip aplikasi dari bidangnya. Prinsip-prinsip ini
meliputi struktur data yang digunakan dalam representasi pengetahuan, algoritma
yang diperlukan untuk mengaplikasikan pengetahuan tersebut, serta bahasa dan teknik
pemrograman yang digunakan dalam mengimplementasikannya.
Dari beberapa perspektif, AI dapat dipandang sebagai:
1. Dari perspektif kecerdasan, AI adalah bagaimana membuat mesin yang cerdas dan
dapat melakukan hal-hal yang sebelumnya hanya dapat dilakukan manusia.
2. Dari perspektif bisnis, AI adalah sekelompok alat bantu (tools) yang berdayaguna
dan metodologi yang menggunakan alat-alat bantu tersebut untuk menyelesaikan
masalah-masalah bisnis.
3. Dari perspektif pemrograman, AI meliputi studi tentang pemrograman simbolik,
pemecahan masalah, dan proses pencarian (search).
4. Dari perspektif penelitian:
a. Riset tentang AI dimulai pada awal tahun 1960-an, percobaan pertama adalah
membuat program permainan catur, membuktikan teori, dan general problem
solving.
b. Artificial intelligence adalah nama pada akar dari studi area. Ada dua hal yang
sangat mendasar mengenai penelitian-penelitian AI, yaitu knowledge
representation (representasi pengetahuan) dan search (pelacakan). Para peneliti
AI terus mengembangkan berbagai jenis teknik baru dalam menangani
sejumlah permasalahan yang tergolong ke dalam AI seperti vision dan
percakapan, pemrosesan bahasa alami, dan permasalahan khusus seperti
diagnosa medis.
Setiap permainan memiliki aturan main. Hal ini mempermudah upaya menghasilkan
ruang pencarian dan memberikan kebebasan pada para peneliti dari bermacam-macam
ambisi dan kompleksitas sifat serta kurangnya struktur permasalahan. Papan
konfigurasi yang digunakan untuk memainkan permainan ini mudah direpresentasikan
pada komputer dan tidak memerlukan bentuk yang kompleks. Permainan dapat
menghasilkan sejumlah besar pencarian ruang. Hal ini cukup besar dan kompleks
sehingga membutuhkan suatu teknik yang tangguh untuk menentukan alternatif
pengeksplorasian ruang permasalahan. Teknik ini dikenal dengan nama heuristic dan
merupakan area utama dari penelitian tentang AI. Banyak hal yang biasanya dikenal
sebagai kecerdasan tampaknya berada dalam heuristic yang digunakan oleh manusia
untuk menyelesaikan permasalahannya.
2. Representasi Ruang Keadaan
Representasi masalah dalam Ruang Keadaan (State Space), yaitu suatu ruang yang
berisi semua keadaan yang mungkin. Kita dapat memulai bermain catur dengan
menempatkan diri pada keadaan awal, kemudian bergerak dari satu keadaan ke
keadaan yang lain sesuai dengan aturan yang ada, dan mengakhiri permainan jika
salah satu telah mencapai tujuan. Jadi untuk mendeskripsikan masalah dengan baik
harus :
- Mendefinisikan suatu ruang keadaan (state space)
- Menetapkan satu atau lebih keadaan awal (initial state)
- Menetapkan satu atau lebih tujuan (goal state)
- Menetapkan kumpulan aturan

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.

Gambar 2.1 Breadth – First Search


Keuntungan
- tidak akan menemui jalan buntu, menjamin ditemukannya solusi (jika
solusinya memang ada) dan solusi yang ditemukan pasti yang paling baik
- jika ada 1 solusi, maka breadth – first search akan menemukannya,jika
ada lebih dari 1 solusi, maka solusi minimum akan ditemukan.
- Kesimpulan : complete dan optimal
Kelemahan :
- membutuhkan memori yang banyak, karena harus menyimpan semua
simpul yang pernah dibangkitkan. Hal ini harus dilakukan agar BFS
dapat melakukan penelusuran simpulsimpul sampai di level bawah
- membutuhkan waktu yang cukup lama

2. Pencarian mendalam pertama (Depth – First Search)


Pencarian dilakukan pada suatu simpul dalam setiap level dari yang paling
kiri. Jika pada level yang paling dalam tidak ditemukan solusi, maka pencarian
dilanjutkan pada simpul sebelah kanan dan simpul yang kiri dapat dihapus dari
memori. Jika pada level yang paling dalam tidak ditemukan solusi, maka
pencarian dilanjutkan pada level sebelumnya. Demikian seterusnya sampai
ditemukan solusi.

Gambar 2.2 Depth – First Search


Keuntungan :
- membutuhkan memori relatif kecil, karena hanya node-node pada lintasan
yang aktif saja yang disimpan
- Secara kebetulan, akan menemukan solusi tanpa harus menguji lebih
banyak lagi dalam ruang keadaan, jadi jika solusi yang dicari berada pada
level yang dalam dan paling kiri, maka DFS akan menemukannya dengan
cepat = waktu cepat
Kelamahan :
- Memungkinkan tidak ditemukannya tujuan yang diharapkan, karena jika
pohon yang dibangkitkan mempunyai level yang sangat dalam (tak
terhingga) = tidak complete karena tidak ada jaminan menemukan solusi
- Hanya mendapat 1 solusi pada setiap pencarian, karena jika terdapat lebih
dari satu solusi yang sama tetapi berada pada level yang berbeda, maka
DFS tidak menjamin untuk menemukan solusi yang paling baik = tidak
optimal.

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.

5. Bahasa Pemrograman Java


Java adalah bahasa pemrograman yang dapat dijalankan di
berbagai komputer termasuk telepon genggam. Bahasa ini awalnya dibuat oleh James
Gosling saat masih bergabung di Sun Microsystems saat ini merupakan bagian
dari Oracle dan dirilis tahun 1995. Bahasa ini banyak mengadopsi sintaksis yang
terdapat pada C dan C++ namun dengan sintaksis model objek yang lebih sederhana
serta dukungan rutin-rutin aras bawah yang minimal. Aplikasi-aplikasi berbasis java
umumnya dikompilasi ke dalam p-code (bytecode) dan dapat dijalankan pada
berbagai Mesin Virtual Java (JVM). Java merupakan bahasa pemrograman yang
bersifat umum/non-spesifik (general purpose), dan secara khusus didisain untuk
memanfaatkan dependensi implementasi seminimal mungkin. Karena
fungsionalitasnya yang memungkinkan aplikasi java mampu berjalan di beberapa
platform sistem operasi yang berbeda, java dikenal pula dengan slogannya, "Tulis
sekali, jalankan di mana pun". Saat ini java merupakan bahasa pemrograman yang
paling populer digunakan, dan secara luas dimanfaatkan dalam pengembangan
berbagai jenis perangkat lunak aplikasi ataupun aplikasi

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

Gambar 3.1 Flowchart


Pada awal aplikasi akan dipilihkan pada 5 menu yaitu randomize untuk mengacak
kotak angka pada puzzle, reset untuk mengurutkan kotak angka sesuai dengan
keadaan tujuan, Solve – A* untuk menyelesaikan puzzle dengan metode A* serta
menampilkan waktu yang diperlukan, move berapa dan extend nodes yang
dilakukan, Solve – DFS untuk menyelesaikan puzzle dengan metode DFS serta
menampilkan waktu yang diperlukan, move berapa dan extend nodes yang
dilakukan, dan yang terakhir adalah speed untuk mengatur kecepatan move kotak
kotak pada puzzle.

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{

public static enum MOVES{UP, DOWN, RIGHT, LEFT};


public static enum SPEED{SLOW, MEDIUM, FAST};
private int timerSpeed = 500;
public static final byte[] GOAL = {1, 2, 3, 4, 5, 6, 7, 8, 0};
private byte[] current = {1, 2, 3, 4, 5, 6, 7, 8, 0};
private boolean solving = false;

public boolean isSolving(){


return this.solving;
}

public byte[] getCurrentBoard(){


return current.clone();
}

public void setCurrentBoard(byte[] b){


this.current = b;
}

public void setTimerSpeed(SPEED speed){


switch(speed){
case SLOW:
this.timerSpeed = 700;
break;
case MEDIUM:
this.timerSpeed = 300;
break;
case FAST:
this.timerSpeed = 100;
break;
}
}

//handles the tiles' press


//figures out the tile's position relative to the blank and moves accordingly
public void tilePressed(int btn){
int blank = getBlankIndex(current);
if(btn == blank-1){
move(current, MOVES.LEFT);
}else if(btn == blank+1){
move(current, MOVES.RIGHT);
}else if(btn == blank+3){
move(current, MOVES.DOWN);
}else if(btn == blank-3){
move(current, MOVES.UP);
}
}

//make a move on the given board, changes the given board


//if the move is invalid, do nothing
//Note that the move is according to the blank, i.e. the blank moves UP or DOWN and so on
public static void move(byte[] board, MOVES toMove){
int blank = getBlankIndex(board);
if(blank == -1) return; //impossible, but just to be sure
switch(toMove){
case UP:
if(blank/3 != 0) swap(board, blank, blank-3);
break;
case DOWN:
if(blank/3 != 2) swap(board, blank, blank+3);
break;
case RIGHT:
if(blank%3 != 2) swap(board, blank, blank+1);
break;
case LEFT:
if(blank%3 != 0) swap(board, blank, blank-1);
break;
}
}

public boolean isSolved(){


return Arrays.equals(this.current, this.GOAL);
}
//resets the board
public void resetBoard(){
for(int i = 0 ; i < current.length-1 ; ++i) current[i] = (byte)(i+1);
current[current.length - 1] = 0;
}

//generates a random, solvable board and makes it the current board


public void randomizeBoard(){
byte board[];
while(!isSolvable(board = getRandomBoard()));
current = board;
}

//makes a state at random, not necessarly solvable


private byte[] getRandomBoard(){
boolean f[] = new boolean[current.length];
byte board[] = new byte[current.length];
Random rand = new Random();

//randomizes each element and make sure no element is repeated


for(int i = 0 ; i < current.length ; ++i){
byte t;
while(f[t = (byte)rand.nextInt(9)]);
f[t] = true;
board[i] = t;
}
return board;
}

//checks if the given state is solvable or not


private boolean isSolvable(byte board[]){
//inversion counter
int inv = 0;
for(int i = 0 ; i < board.length ; ++i){
if(board[i] == 0) continue;
for(int j = i+1 ; j < board.length ; ++j){
//wrong precedence, count an inversion
if(board[j] != 0 && board[i] > board[j]) ++inv;
}
}

//the board is solvable if the number of inversions is even


return (inv % 2 == 0);
}

//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;
}

//swaps 2 elemets in the given board


//if the swap is impossible (index out of range), do nothing
public static void swap(byte[] board, int i, int j){
try{
byte iv = board[i];
byte jv = board[j];
board[i] = jv;
board[j] = iv;
}catch(ArrayIndexOutOfBoundsException ex){
//if i or j is out of range, do nothing
}
}

//used for debugging :D


public static void print(byte[] b){
for(int i = 0 ; i < b.length ; ++i)
System.out.print(b[i] + " ");
System.out.println("");
}

public void solve(GUI gui, Solvers.SOLVE_METHOD method){

Map<String, byte[]> parent = null;

this.solving = true;

long time = System.nanoTime();


switch(method){
case A_STAR:
parent = Solvers.aStar(getCurrentBoard().clone());
break;
case DFS:
parent = Solvers.dfs(getCurrentBoard().clone());
break;
}

time = (System.nanoTime() - time) / 1000000;

//use backtracking like technique to get the moves to be made


//solution states (not moves) are saved into the stack in order to be executed
Stack<byte[]> nextBoard = new Stack<>();
nextBoard.add(GOAL.clone());
while(!Arrays.equals(nextBoard.peek(), this.current))
nextBoard.add(parent.get(make(nextBoard.peek())));
nextBoard.pop();

String status = String.format("<html>%d ms<br/>%d moves<br/>%d expanded nodes</html>", time,


nextBoard.size(), Solvers.times);
gui.setStatus(status);

//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);
}

//start the gui, let the magic begin :D


GUI gui = new GUI();
gui.setVisible(true);

- 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 {

public final BoardControl boardControl;


private final JButton tiles[];
//private final BasicPlayer player;

/**
* Creates new form GUI
*/
public GUI() {

//frame Title
super("8 Puzzle");

//set GUI settings


initComponents();
this.setLocationRelativeTo(null); //center the frame in the screen on open
this.setResizable(false);
this.setAlwaysOnTop(true);

//Global variabels intialization


this.tiles = new JButton[]{Tile_1, Tile_2, Tile_3, Tile_4, Tile_5, Tile_6, Tile_7, Tile_8, Tile_0};
this.boardControl = new BoardControl();

//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;

ActionListener me(int i){


num = i;
return this;
}

@Override
public void actionPerformed(ActionEvent e) {
if(GUI.this.boardControl.isSolving()) return;
GUI.this.boardControl.tilePressed(num);
GUI.this.drawBoard();
}
}.me(i));
}

//action listener for the reset button


Button_Reset.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
GUI.this.boardControl.resetBoard();
GUI.this.drawBoard();
}
});

//action listener for the randomize button


Button_Rand.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(GUI.this.boardControl.isSolving()) return;
GUI.this.boardControl.randomizeBoard();
GUI.this.drawBoard();
}
});

//action listener for the solve button


Button_Solve_A.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(GUI.this.boardControl.isSolving()) return;
GUI.this.boardControl.solve(GUI.this, Solvers.SOLVE_METHOD.A_STAR);
GUI.this.pack();
//GUI.this.setLocationRelativeTo(null);
}
});

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
}

//draw the current board on the tiles


public final void drawBoard(){
final byte[] board = boardControl.getCurrentBoard();
int empty = -1;
//label the buttons (the tiles)
for(int i = 0 ; i < board.length ; ++i){
if(board[i] == 0) empty = i;
else tiles[i].setText(String.valueOf(board[i]));
}

//show all the buttons then hide the blank one


for(JButton tile : tiles) tile.setVisible(true);
tiles[empty].setVisible(false);

//notify the panel to update


Main_Middle.repaint();
Main_Middle.revalidate();
}

public void setStatus(String stat){


this.Label_Status.setText(stat);
}

/**
* 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;

jPanel1 = new javax.swing.JPanel();


Main_Right = new javax.swing.JPanel();
ButtonsPanel = new javax.swing.JPanel();
Button_Rand = new javax.swing.JButton();
Button_Reset = new javax.swing.JButton();
Button_Solve_A = new javax.swing.JButton();
Button_Solve_DFS = new javax.swing.JButton();
Button_Speed = new javax.swing.JButton();
jPanel2 = new javax.swing.JPanel();
Label_Status = new javax.swing.JLabel();
Main_Middle = new javax.swing.JPanel();
Tile_1 = new javax.swing.JButton();
Tile_2 = new javax.swing.JButton();
Tile_3 = new javax.swing.JButton();
Tile_4 = new javax.swing.JButton();
Tile_5 = new javax.swing.JButton();
Tile_6 = new javax.swing.JButton();
Tile_7 = new javax.swing.JButton();
Tile_8 = new javax.swing.JButton();
Tile_0 = new javax.swing.JButton();

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_Rand.setFont(new java.awt.Font("Ubuntu", 0, 16)); // NOI18N


Button_Rand.setText("Acak");
Button_Rand.setFocusable(false);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
ButtonsPanel.add(Button_Rand, gridBagConstraints);

Button_Reset.setFont(new java.awt.Font("Ubuntu", 0, 16)); // NOI18N


Button_Reset.setText("Restart");
Button_Reset.setFocusable(false);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
ButtonsPanel.add(Button_Reset, gridBagConstraints);

Button_Solve_A.setFont(new java.awt.Font("Ubuntu", 0, 16)); // NOI18N


Button_Solve_A.setText("Search - A*");
Button_Solve_A.setFocusable(false);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
ButtonsPanel.add(Button_Solve_A, gridBagConstraints);

Button_Solve_DFS.setFont(new java.awt.Font("Ubuntu", 0, 16)); // NOI18N


Button_Solve_DFS.setText("Search - DFS");
Button_Solve_DFS.setFocusable(false);
Button_Solve_DFS.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Button_Solve_DFSActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
ButtonsPanel.add(Button_Solve_DFS, gridBagConstraints);

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);

Main_Middle.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));


Main_Middle.setLayout(new java.awt.GridBagLayout());

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

private void Button_Solve_DFSActionPerformed(java.awt.event.ActionEvent evt) {//GEN-


FIRST:event_Button_Solve_DFSActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_Button_Solve_DFSActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton Button_Rand;
private javax.swing.JButton Button_Reset;
private javax.swing.JButton Button_Solve_A;
private javax.swing.JButton Button_Solve_DFS;
private javax.swing.JButton Button_Speed;
private javax.swing.JPanel ButtonsPanel;
private javax.swing.JLabel Label_Status;
public javax.swing.JPanel Main_Middle;
private javax.swing.JPanel Main_Right;
private javax.swing.JButton Tile_0;
private javax.swing.JButton Tile_1;
private javax.swing.JButton Tile_2;
private javax.swing.JButton Tile_3;
private javax.swing.JButton Tile_4;
private javax.swing.JButton Tile_5;
private javax.swing.JButton Tile_6;
private javax.swing.JButton Tile_7;
private javax.swing.JButton Tile_8;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
// End of variables declaration//GEN-END:variables
}

- 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;

public class Solvers {

public static enum SOLVE_METHOD{A_STAR, DFS};

//global variables needed for DFS


private static final Map<String, byte[]> dfs_parent = new HashMap<>();
private static final Set<String> dfs_vis = new HashSet<>();

//to count the number of expanded nodes


public static long times;

//solve the current position with A* search


public static Map<String, byte[]> aStar(byte[] current){
PriorityQueue<State> q = new PriorityQueue<>();
Map<String, Integer> dist = new HashMap<>();
Map<String, byte[]> parent = new HashMap<>();
times = 0;

//intialize the distance of the current state to be 0


dist.put(stringify(current), 0);

//add the current state to the front of the states queue


q.add(new State(current, 0));

//A* Algorithm ...


while(!q.isEmpty()){
State crnt = q.poll();
times++;
if(Arrays.equals(crnt.getBoard(), BoardControl.GOAL)) break;
for(State child : crnt.getNextStates()){
if(dist.getOrDefault(stringify(child.getBoard()), Integer.MAX_VALUE) > child.getCost()){
parent.put(stringify(child.getBoard()), crnt.getBoard());
dist.put(stringify(child.getBoard()), child.getCost());
q.add(child);
}
}
}

return parent;
}

//Solve the game with DFS (Very very very inefficient)


//this method uses a stack to simulate the recursion, I had problems implementing deep recursion in java
public static Map<String, byte[]> dfs(byte[] current){
Stack<State> stack = new Stack<>();
Map<String, byte[]> parent = new HashMap<>();
Set<String> vis = new HashSet<>();

times = 0;

//add the current state to the front of the states queue


stack.push(new State(current, 0));

//the simlated recursion part


while(!stack.isEmpty()){
State crnt = stack.pop();
vis.add(stringify(crnt.getBoard()));
times++;
if(Arrays.equals(crnt.getBoard(), BoardControl.GOAL)) break;
for(State child : crnt.getNextStates()){
if(vis.contains(stringify(child.getBoard()))) continue;
parent.put(stringify(child.getBoard()), crnt.getBoard());
stack.push(child);
}
}

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;
}

V. Hasil dan Pembahasan


1. Hasil Simulasi
Keadaan Awal

Gambar 5.1 Keadaan Awal


Pada keadaan awal kotak kotak ditata secara acak tidak berurutan dan akan
diselesaikan dengan metode DFS untuk mencapai keadaan tujuan dengan cara
menggeser kotak kotak satu per satu ke arah kotak kosong secara vertical atau
horizontal.

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.

Anda mungkin juga menyukai