Algoritma Backtracking (Kasus 8 Ratu)
Transcript of Algoritma Backtracking (Kasus 8 Ratu)
Algoritma Backtracking (Kasus 8 Ratu)
Disusun oleh :
1. ERLANGGA (50406258)
2. IDHAM JULHANDI (50406367)
3. R.IBRAHIM SENOAJI (50406568)
4. ROMMY KAMAL (50406645)
5. TAUFIQURAHMAN (50406709)
6. FIRMAN ISAI (50406296)
Kelas : 3IA12
JURUSAN TEKNIK INFORMATIKA
FAKULTAS TEKNOLOGI INDUSTRI
UNIVERSITAS GUNADARMA
BAB I
MATERI
Dasar Teori
Runut balik (backtracking) merupakan algoritma yang berbasis pada DFS (Depth First Search) untuk mencari solusi persoalan secara lebih optimal. Runut balik merupakan perbaikan dari algoritma brute-force, secara sistematis mencari solusi persoalan di antara semua kemungkinan solusi yang ada. Perbedaan utamanya adalah pada konsep dasarnya, yauti pada backtracking semua solusi dibuat dalam bentuk pohon solusi (tree), dan kemudian pohon tersebut akan ditelusuri secara DFS sehingga ditemukan solusi terbaik yang diinginkan.
Dengan metode runut-balik, kita tidak perlu memeriksa semua kemungkinan solusi yang ada. Hanya pencarian yang mengarah ke solusi saja yang selalu dipertimabangkan. Akibatnya, waktu pencarian dapat dihemat. Saat ini algoritma runut balik balik diterapkan untuk permainan games (seperti permainan tic-tac-toe, menemukan jalan keluar dalam sebuah labirin, catur, dan lain-lain) dan masalah-masalah pada bidang kecerdasan buatan (artificial intelligence).
Misalkan pohon di atas menggambarkan solusi dari suatu persoalan. Jika kita ingin mencari solusi dari A ke E, maka jalur yang harus ditempuh adalah (A-B-E). Demikian juga untuk solusi-solusi yang lain. Algoritma Backtracking akan memeriksa jalur secara DFS, yaitu dari solusi terdalam pertama yang ditemui yaitu solusi E. Jika ternyata E bukanlah solusi yang diharapkan, maka pencarian akan dilanjutkan ke F. Jalur yang harus dilalui untuk bisa mencapai E adalah (A-B-E) dan untuk mencapai F adalah (A-B-F). Kedua solusi tersebut memiliki jalur awal yang sama, yaitu (A-B). Jadi, daripada memeriksa ulang jalur dari A kemudian B, maka jalur (A-B) disimpan dulu dan langsung memeriksa solusi F. Untuk kasus pohon yang lebih rumit, cara ini dianggap lebih efisien daripada jika menggunakan algoritma Brute-Force.
Algoritma Backtracking digunakan untuk membuat Artificial Intelligence pada board games seperti catur, othello, dan checker. Dengan algoritma ini dapat dibuat pohon solusi sampai dengan kedalaman tertentu dari current status, dan dipilih solusi yang dapat membantu user menemukan langkah-langkah yang nantinya akan menghasilkan pohon solusi yang menguntungkan bagi user. Cara ini dipakai sebagai Artificial Intelligence yang digunakan untuk menyelesaikan dynamic problem. Beberapa contoh penggunaan dari algoritma Backtrack dari suatu masalah statik adalah untuk memecahkan masalah N-Queen problem dan Maze Solver.
Pengguna N-Queen problem adalah permasalahan di mana user harus mencari cara bagaimana meletakkan bidak Queen catur sebanyak n buah pada Bidang catur atau pada Bidang berukuran nxn sedemikian rupa sehingga tidak ada satu bidakpun yang dapat memakan bidak lainnya hanya dengan1 langkah (1 gerakan). Meskipun ada kemungkinan terdapat lebih dari satu cara untuk mendapatkan solusinya, tetapi tidak perlu dilakukan proses pencarian untuk mendapatkan semua solusinya.Untuk beberapa kasus tertentu perlu dilakukan pencarian terhadap semua solusi sehingga dapat dipilih satu solusi terbaik.
Implementasi Backtracking
Algoritma Backtracking akan mencoba menelsuri semua solusi yang mungkin, sehingga pertama-tama harus dibuat algoritma dasar yang dapat melakukan pencarian terhadap semua kemungkinan solusi. Lalu, algoritma tersebut diperbaiki dan dikembangkan sehingga cara pencarian solusinya lebih efisien, efektif, dan sistematis. Algoritma tersebut dibuat untuk menelusuri kemungkinan solusi pada suatu pohon solusi abstrak. Algoritma Backtracking dianggap sebagai perbaikan dari algoritma Brute-Force karena pada Backtracking penelusuran terhadap cabang-cabang dapat dihentikan jika pada suatu titik cabang tertentu diketahui bahwa penelusuran tersebut tidak akan mencapai solusi yang diinginkan. Dengan demikian, kompleksitas program dapat dikurangi.
Saat dilakukan penelusuran terhadap B, dipastikan bahwa jalur tersebut tidak akan menghasilkan solusi yang diinginkan. Maka program langsung menghentikan proses pencarian dan kemudian langsung dilanjutkan ke jalur C. Penelusuran terhadap jalur (A-B-E) dan (A-B-F) pun dihentikan. Hal itu membuat kompleksitas waktu yang diperlukan juga berkurang, sehingga dapat menghemat waktu yang diperlukan. Semakin cepat terdeteksi bahwa jalur yang ditempuh tidak akan menghasilkan solusi optimal, maka program akan bekerja dengan lebih efisien.
Dalam Backtrack, jika kita ingin kembali pada kondisi sebelumnya, kita harus menyimpan hasil perhitungan dari kondisi awal sampai dengan kondisi tersebut. Pada bahasa pemrograman yang telah bisa menangani fungsi-fungsi atau prosedur-prosedur rekursif, penyimpanan dapat lebih mudah dilakukan. Manajemen memori dilakukan sepenuhnya oleh compiler. Pada bahasa pemrograman lainnya, algoritma Backtrack masih dapat diimplementasikan meskipun manajemen memori harus dilakukan oleh programmer. Manajemen memori yang baik adalah dengan menggunakan pointer atau dynamic array, karena kedalaman pohon solusi yang harus ditelusuri biasanya bervariasi dan tidak dapat ditentukan.
Algoritma Runut-balik untuk Persoalan 8-Ratu
(a) Versi iteratif
• Dua buah ratu terletak pada baris yang sama, berarti i = k
• Dua buah ratu terletak pada kolom yang sama, berarti j=l
• Dua buah ratu terletak pada diagonal yang sama, berarti � i-j=k-l atau i+j=k+l
⇔ i-k=j-l atau k-i=j-l
⇔ j-l= i-k
1 2 3 4 5 6 7 8 1
2
3
4
5
6
7
8
Skema iterative
(b) Versi rekursif
Algoritma:
• Inisialisasi x[1], x[2], …, x[N] dengan 0
for i←N to n do
x[i]←0
endfor
procedure N_RATU_I(input N:integer) { Mencetak semua solusi penempatan N buah ratu pada petak papan catur N x N tanpa melanggar kendala; versi iteratif Masukan: N = jumlah ratu Keluaran: semua solusi x = (x[1], x[2], …, x[N]) dicetak ke layar. } Deklarasi k : integer Algoritma: k←1 {mulai pada baris catur ke-1} x[1]←0 {inisialisasi kolom dengan 0} while k > 0 do x[k]←x[k]+1 {pindahkan ratu ke kolom berikutnya} while (x[k] ≤ N) and (not TEMPAT(k)) do {periksa apakah ratu dapat ditempatkan pada kolom x [k]} x[k]:=x[k] + 1 endwhile {x[k] > n or TEMPAT(k) } if x[k]≤ n then { kolom penempatan ratu ditemukan } if k=N then { apakah solusi sudah lengkap?} CetakSolusi(x,N) { cetak solosi} else k←k+1 {pergi ke baris berikutnya} x[k]←0 {inisialisasi kolom dengan 0} endif else k←k-1 { runut-balik ke baris sebelumnya} endif endwhile { k = 0 }
• Panggil prosedur N_RATU_R(1)
procedure N_RATU_R(input k:integer) { Menempatkan ratu pada baris ke-k pada petak papan catur N x N tanpa melanggar kendala; versi rekursif Masukan: N = jumlah ratu Keluaran: semua solusi x = (x[1], x[2], …, x[N]) dicetak ke layar. } Deklarasi stop : boolean Algoritma: stop←false while not stop do x[k]←x[k]+1 { pindahkan ratu ke kolom berikutnya } while (x[k] ≤ n) and (not TEMPAT(k)) do { periksa apakah ratu dapat ditempatkan pada kolom x[k] } x[k]←x[k]+1 endwhile { x[k] > n or TEMPAT(k) } if x[k] ≤ N then { kolom penempatan ratu ditemukan } if k=N then { apakah solusi sudah lengkap? } CetakSolusi(x,N) { cetak solusi } else N_RATU_R(k+1) else { x[k] > N � gagal, semua kolom sudah dicoba } stop←true x[k]←0 endif endwhile {stop}
Tampilan awal program
BAB II
APLIKASI
Kasus
Persoalan 8 Ratu, diberikan sebuah bidang yang berukuran 8x8 dan delapan buah ratu, dimana 8
ratu harus ditempatkan pada petak-petak b idang catur sedemikian hingga tidak ada ratu lain yang
menempati posisi ratu pada baris yang sama, atau pada satu kolom yang sama, atau pada satu diagonal
yang sama.
Screen Shoot
Ketika program dimainkan
Ketika user menekan tombol Solve
Source code
File Bidang.java
import java.awt.*;
import java.awt.event.*;
public class Bidang extends Canvas implements MouseListener
{
int[][] kotak = new int[8][8];
int lebar,tinggi;
Graphics grafik = this.getGraphics(); //menggambar objek grafik
public Bidang() //konstruktor
{
addMouseListener(this);
initBidang();
}
public void initBidang()
{
//pertama, beri harga awal dahulu pada setiap kotak
for(int i=0;i<8;i++)
for(int j=0;j<8;j++)
kotak[i][j]=0;
}
public void paint(Graphics g)
{
g = grafik;
//membagi kotak kemudian memberi garis
lebar = getBounds().width/8;
/**
getBounds
public Rectangle getBounds()
Gets the bounds of this component in the form of a Rectangle object.
bounds specify this component's width, height, and location relative to its parent.
Returns:
a rectangle indicating this component's bounds
See Also:
setBounds(int, int, int, int)
**/
tinggi = getBounds().height/8;
for(int i=0;i<8;i++)
for(int j=0;j<8;j++)
beriGaris(i,j);
}
private void beriGaris(int x,int y)
{
int dark = 0;
grafik.setColor(Color.black);
grafik.drawRect(x*lebar,y*tinggi,lebar,tinggi);
/**
*
drawRect
public void drawRect(int x,
int y,
int width,
int height)
Draws the outline of the specified rectangle. The left and right edges of the rectangle are
at x and x + width. The top and bottom edges are at y and y + height. The rectangle is drawn
using the graphics context's current color.
Parameters:
x - the x coordinate of the rectangle to be drawn.
y - the y coordinate of the rectangle to be drawn.
width - the width of the rectangle to be drawn.
height - the height of the rectangle to be drawn.
*
**/
if((x+y)%2==0)
dark=20;//default abu-abu, jika kotak genap warnanya putih. (0+230=abu-abu, 20+230=putih).
switch(kotak[x][y])
{
case 0:grafik.setColor(new Color(230+dark,230+dark,230+dark));break;//tampilan awal dan clear
case 1:grafik.setColor(new Color(160+dark,110+dark,110+dark));break;
//posisi ratu secara horizontal,vertikal,serong
case 2:grafik.setColor(new Color(0,0,0));break;//hitam (letak ratu)
}
grafik.fillRect(x*lebar+1,y*tinggi+1,lebar-1,tinggi-1);
/**
public abstract void fillRect(int x,
int y,
int width,
int height)
Fills the specified rectangle. The left and right edges of the rectangle are at x and x +
width - 1. The top and bottom edges are at y and y + height - 1. The resulting rectangle covers
an area width pixels wide by height pixels tall. The rectangle is filled using the graphics
context's current color.
*
**/
}
public void mouseExited(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mousePressed(MouseEvent me)
{
int x = me.getX()/lebar;
int y = me.getY()/tinggi;
if(cek(x,y))
{
if (kotak[x][y]==0)
taruhRatu(x,y,true);
//pertama kali ratu diletakkan, semua kordianat bernilai 0.
else if (kotak[x][y]==2)
taruhRatu(x,y,false);
}
}
private void taruhRatu(int x,int y,boolean taruh)
{
grafik=this.getGraphics();
if(taruh)
kotak[x][y]=2;
else
kotak[x][y]=0;
for(int i=0;i<8;i++)
{
if(i!=y) pindah(x,i,taruh);//secara vertikal
if(i!=x) pindah(i,y,taruh);//secara horizontal
}
for(int i=1;cek(x+i,y+i);i++)
pindah(x+i,y+i,taruh);//serong kanan bawah
for(int i=1;cek(x+i,y-i);i++)//y bernilai min (-), semakin ke atas
pindah(x+i,y-i,taruh);//serong kanan atas
for(int i=1;cek(x-i,y+i);i++)//x bernilai min(-), semakin ke bawah
pindah(x-i,y+i,taruh);//serong kiri bawah
for(int i=1;cek(x-i,y-i);i++)// x dan y bernilai min, semakin ke kiri atas
pindah(x-i,y-i,taruh);//serong kiri atas
beriGaris(x,y);
}
private void pindah(int x,int y,boolean taruh)
{
if(taruh && kotak[x][y]==0)
kotak[x][y]=1;// jika kotak hitam tersebut di klik lagi ubah flagnya.
else if(!taruh && kotak[x][y]==1)
kotak[x][y]=0;
beriGaris(x,y);
}
private boolean cek(int x, int y)
{
return (x>=0 && x<8 && y>=0 && y<8);
}
public boolean solve(int y) {
int i,j;
boolean r = false;
for (i=0;i<8;i++) {
if (kotak[i][y] == 0) {
taruhRatu(i,y,true);
if (y == 7) {
return true;
} else {
if (solve(y+1)) {
return true;
} else {
taruhRatu(i,y,false);
}
}
}
}
return false;
}
}
File RatuApplet.java
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class RatuApplet extends Applet implements ActionListener
{
Button refresh = new Button("Refresh");
Button solve = new Button("Solve");
Bidang Bidang = new Bidang();
public void init()
{
setLayout(new BorderLayout());
add("Center",Bidang);
Panel panel = new Panel();
add("South",panel);//kemungkinan besar, defaultnya BorderLayout
panel.setLayout(new GridLayout(1,5));
panel.add(new Label(""));
panel.add(refresh);
panel.add(new Label(""));
panel.add(solve);
panel.add(new Label(""));
refresh.addActionListener(this);
solve.addActionListener(this);
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource()==refresh)
{
Bidang.initBidang();
Bidang.paint(Bidang.getGraphics());
}else if (ae.getSource() == solve) {
Bidang.initBidang();
Bidang.paint(Bidang.getGraphics());
Bidang.solve(0);
}
}
}
Logika program
File Bidang.java
Pada program ini kita menggunakan 2 paket yaitu paket “java.awt.*” dan “java.awt.event.*”,
paket java.awt digunakan untuk membuat tampilan dan menggambar grafik serta gambar, sedangkan
java.awt.event.* digunakan untuk menangani penanganan kejadian.
Pada class Bidang yang di-extends dari kelas Canvas dan mengimplementasikan dari interface
MouseListener. Interface MouseListener sendiri berguna untuk menerima inputan dari mouse (press,
release, click, enter, and exit). Untuk membuat 16 kotak maka kita menggunakan array 2 dimensi atau
matriks dengan dimensi 8x8, selanjutnya untuk variabel lebar dan tinggi kita deklarasikan bertipe
integer. Method getGraphics() sendiri berguna untuk menggambar objek grafik dimana objeknya
diambil dari kelas grafik itu sendiri dengan menghubungkan ke variabel grafik. Method Bidang() sebagai
konstruktor, terdapat 2 method yaitu addMouseListener(this) dan initBidang(). Pada konstruktor
tersebut memanggil method initBidang().
import java.awt.*;
import java.awt.event.*;
public class Bidang extends Canvas implements MouseListener
{
int[][] kotak = new int[8][8];
int lebar,tinggi;
Graphics grafik = this.getGraphics();
public Bidang() //konstruktor
{
addMouseListener(this);
initBidang();
}
Pada method initBidang(), berguna untuk memberi harga awal pada setiap kotak dengan nilai 0.
Karena menggunakan array 2 dimensi maka kita menggunakan 2 perulangan yang berguna sebagai batas
elemen yang diwakili variabel i dan j.
Method paint digunakan untuk membagi kotak yang telah kita buat dengan parameter melalui
method grafik. Kita membagi kotak dengan statement getBounds menurut lebar dan tingginya
sebanyak 8 kotak. Kemudian kita berikan garis pada kotak yang telah kita bagi dengan memanggil
method beriGaris(i,j).
public void initBidang()
{
//pertama, beri harga awal dahulu pada setiap kotak
for(int i=0;i<8;i++)
for(int j=0;j<8;j++)
kotak[i][j]=0;
}
public void paint(Graphics g)
{
g = grafik;
//membagi kotak kemudian memberi garis
lebar = getBounds().width/8;
tinggi = getBounds().height/8;
for(int i=0;i<8;i++)
for(int j=0;j<8;j++)
beriGaris(i,j);
}
private void beriGaris(int x,int y)
{
int dark = 0;
grafik.setColor(Color.black);
grafik.drawRect(x*lebar,y*tinggi,lebar,tinggi);
//public void drawRect(int x,int y,int width,int height)
if((x+y)%2==0)
dark=20;
switch(kotak[x][y])
{
case 0:grafik.setColor(new Color(230+dark,230+dark,230+dark));break;
case 1:grafik.setColor(new Color(160+dark,110+dark,110+dark));break;
case 2:grafik.setColor(new Color(0,0,0));break;
}
grafik.fillRect(x*lebar+1,y*tinggi+1,lebar-1,tinggi-1); //beri warna
}
Pada method beriGaris ini, kita akan memberikan garis untuk kotak yang telah kita bagi pada
method paint. Pertama, kita deklarasikan variabel dark sebagai integer dengan nilai awal 0(nol). Setelah
itu, kita panggil method setColor dari class grafik yang fungsinya untuk memberikan warna yaitu
black(hitam). Kemudian kita juga memanggil method drawRect untuk menggambar garis tepi (outline)
dari persegi panjang. Untuk perubahan warna, kita tentukan dengan statement kondisi if sesuai letak
koordinat kotak. Jika x(lebar) + y(tinggi) mod 2 hasilnya adalah 0(nol), maka nilai dari variabel dark akan
menjadi 20.
Kemudian kita tentukan kondisi dengan statement switch- case. Apabila terjadi case 0(nol),
warnanya akan kita set dengan warna baru menggunakan RGB dengan ketentuan Red:230+dark,
Green:230+dark dan Blue:230+dark. Apabila terjadi case 1(satu), warnanya akan kita set dengan warna
baru menggunakan RGB dengan ketentuan R:160+dark, G:110+dark dan B:110+dark. Dan apabila terjadi
case 2(dua), warnanya kita set denga warna baru menggunakan RGB dengan ketentuan R:0, G:0 dan
B:0.(warnanya menjadi hitam). Kita akan mengisi warna sesuai dengan case tersebut dengan method
fillRect.
public void mouseExited(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mousePressed(MouseEvent me)
{
int x = me.getX()/lebar;
int y = me.getY()/tinggi;
if(cek(x,y))
{
if (kotak[x][y]==0)
taruhRatu(x,y,true);
else if (kotak[x][y]==2)
taruhRatu(x,y,false);
}
}
Pada bagian ini, terdapat banyak event-event yang berhubungan dengan mouse. Karena
program ini kita menggunakan event mousePressed, maka kita dapat mengkosongkan event-event yang
tidak digunakan. Jika tidak ditulis, ketika akan melakukan compile program akan menampilkan pesan
error. Pada event mousePressed, jika kita menekan tombol mouse pada suatu kotak, maka titik
koordinat kotak tersebut akan dimasukkan ke dalam variabel, x untuk lebar dan y untuk tinggi. Untuk
kordinat x didapat dari letak ratu diletakkan (dengan memanggil method getX()) dibagi dengan variabel
lebar dari method paint(). Sedangkan kordinat y didapat dari letak ratu dibagi dengan variabel tinggi dari
method paint().
Kemudian, kita akan mengecek letak koordinat kotak dengan memanggil method cek
menggunakan statement if. Method cek() sendiri berguna untuk memeriksa apakah posisi mouse ketika
ratu diletakkan berada dalam keseluruhan interface program, jika masih berada dalam keseluruhan
interface program maka program akan mengembalikan nilai true, jika tidak program tidak akan
memberikan nilai balik. Jika method cek memberikan nilai true, maka akan dilakukan seleksi kondisi
dengan statement if lagi. Apabila nilai dari kotak sama dengan 0(nol), kita masukkan nilai dari x dan y
beserta hasil Boolean ‘true’ pada method taruhRatu, tetapi apabila nilai dari kotak sama dengan 2(dua)
maka kita masukkan nilai dari x dan y beserta hasil Boolean ‘False’ pada method taruhRatu.
private void taruhRatu(int x,int y,boolean taruh)
{
grafik=this.getGraphics();
if(taruh)
kotak[x][y]=2;
else
kotak[x][y]=0;
for(int i=0;i<8;i++)
{
if(i!=y) pindah(x,i,taruh); //vertikal
if(i!=x) pindah(i,y,taruh); //horizontal
}
for(int i=1;cek(x+i,y+i);i++)
pindah(x+i,y+i,taruh); //serong kanan bawah
for(int i=1;cek(x+i,y-i);i++) //y bernilai min (-), semakin ke atas.
pindah(x+i,y-i,taruh); //serong kanan atas
for(int i=1;cek(x-i,y+i);i++)//x bernilai min(-), semakin ke bawah
pindah(x-i,y+i,taruh); //serong kiri bawah
for(int i=1;cek(x-i,y-i);i++)// x dan y bernilai min, semakin ke kiri atas
pindah(x-i,y-i,taruh); //serong kiri atas
beriGaris(x,y);
}
Method taruhRatu ini berguna untuk meletakkan “ratu” ke tempat yang memungkinkan untuk
diletakkan. Sebelumnya, kita akan memanggil fungsi grafik yang telah dibuat. Kemudian, kita lakukan
seleksi kondisi. Apabila nilai dari variable taruh (yang di-input dari method mousePressed) “true”, maka,
kita tentukan nilai dari kotak menjadi 2(dua) dan apabila nilainya “false”, maka nilai dari variable kotak
kita ubah menjadi 0(nol).
Untuk dapat mengetahui posisi ratu secara vertikal atau horizontal agar tidak dapat diletakkan
oleh ratu lainnya, maka kita lakukan perulangan untuk variabel i. Untuk posisi secara vertikal, Jika nilai
dari variable i tidak sama dengan y, maka kita masukkan nilai x, i dan hasil Boolean untuk variable taruh
pada method pindah.
Kita asumsikan kita meletakkan ratu pada posisi (0,0), maka nilai dari variabel x=0, y=0, dan
taruh bernilai true. Karena variabel i sama dengan y maka program tidak akan menyimpan posisi
tersebut secara vertikal. Ketika i=1, karena variabel i tidak sama dengan y maka program akan
menyimpan posisi tersebut secara vertikal pada kotak (0,1) begitu seterusnya sampai pada kotak (0,7).
Lalu untuk posisi secara horizontal, jika nilai i juga tidak sama dengan x, kita masukkan nilai i, y
dan hasil Boolean untuk variable taruh pada method pindah. Jika variabel taruh bernilai false, maka ratu
tidak dapat diletakkan secara horizontal. Sama halnya pada posisi secara vertikal, kita asumsikan kita
meletakkan ratu pada posisi (0,0). Ketika pada posisi (0,0) program tidak akan menyimpan posisi
tersebut secara horizontal. Ketika i=1, karena variabel i tidak sama dengan x maka program akan
menyimpan posisi tersebut pada kotak (1,0) begitu seterusnya sampai pada kotak(7,0) agar tidak
ditempati oleh ratu lainnya.
Untuk bisa menaruh ratu di semua tempat, kita harus mengatur semua kotak agar bisa untuk
menempatkan ratu, atau memindahkan ratu bila tidak bisa diletakkan. Untuk itu, kita adakan
perulangan – perulangan berikut: pada perulangan pertama, untuk menyimpan posisi ratu secara serong
kanan bawah agar tidak ditempati ratu lain, untuk variable x+i dan y+i dengan nilai awal i adalah 1(satu)
berlanjut selama masih bernilai “true” pada method cek, kita masukkan nilai x+i, y+i dan hasil Boolean
untuk variable taruh pada method pindah. Kita asumsikan kita meletakkan ratu pada posisi (0,0), ketika
variabel i=1, maka variabel x=1, dan y=1 (pindah(x+i,y+i,taruh)), karena variabel taruh bernilai 0 (true)
maka posisi tersebut dapat disimpan. Begitu juga seterusnya pada posisi (2,2), (3,3), (4,4), sampai
dengan posisi (8,8).
Kemudian pada perulangan kedua, yaitu secara serong kanan atas, untuk variable x+i dan y-i
dengan nilai awal i adalah 1(satu) berlanjut selama masih bernilai “true” pada method cek(), kita
masukkan nilai x+i, y-i dan hasil Boolean untuk variable taruh pada method pindah. Kita asumsikan kita
meletakkan ratu pada posisi (0,0) variabel i=1, maka variabel x=1, dan y=-1 (pindah(x+i,y-i,taruh)),
karena variabel taruh bernilai 0 (true) maka posisi tersebut dapat disimpan, yaitu pada posisi (1,-1),
begitu seterusnya pada posisi (1,-2), (1,-3), sampai pada posisi (1,-7).
Pada perulangan ketiga, yaitu posisi serong kiri bawah, untuk variable x-i dan y+i dengan nilai
awal i adalah 1(satu) berlanjut selama masih bernilai “true” pada method cek, kita masukkan nilai x-i, y+i
dan hasil Boolean untuk variable taruh pada method pindah. Sama halnya pada perulangan di atas, kita
asumsikan kita meletakkan posisi ratu pada posisi (0,0) variabel i=1, maka variabel x=-1, dan y=1
(pindah(x-i,y+i,taruh)), karena variabel taruh bernilai true maka pada posisi(-1,1) kita dapat
menyimpannya. Begitu juga halnya dengan posisi (-2,1),(-3,1) sampai dengan posisi (-7,1).
Dan pada perulangan keempat, yaitu pada posisi serong kiri atas, untuk variable x-i dan y-i
dengan nilai awal i adalah 1(satu) berlanjut selama masih bernilai “true” pada method cek, kita
masukkan nilai x-i, y-i dan hasil Boolean untuk variable taruh pada method pindah. Kita asumsikan kita
meletakkan ratu pada posisi (0,0) variabel i=1, maka variabel x=-1, dan y=-1 (pindah(x-i,y-i,taruh)),
karena variabel taruh bernilai true maka pada posisi (-1,-1) kita dapat menyimpannya. Sama halnya
dengan posisi (-2,-2), (-3,-3) sampai dengan (-7,-7).
Setelah kita menyimpan posisi dari letak ratu agar tidak ditaruh ratu lain baik secara vertikal,
horizontal, serong kiri atas dan bawah, dan serong kanan atas dan bawah. Selanjutnya kita berikan garis
dengan memanggil method beriGaris(x,y) dengan parameter yang diwakili variabel x dan y yang
merupakan posisi kordinat dari posisi letak ratu tersebut.
private void pindah(int x,int y,boolean taruh)
{
if(taruh && kotak[x][y]==0)
kotak[x][y]=1;
else if(!taruh && kotak[x][y]==1)
kotak[x][y]=0;
beriGaris(x,y);
}
Method pindah ini berfungsi untuk menentukan dimana ratu bisa dipindahkan dan dimana ratu
tidak bisa dipindahkan. Disini, kita lakukan seleksi kondisi. Apabila nilai dari variable taruh adalah “true”
dan nilai dari kotak adalah 0, kita ganti nilai dari kotak menjadi 1, tetapi apabila nilai dari variable taruh
adalah “false” dan nilai dari kotak adalah 1, kita ganti nilai dari kotak menjadi 0. Selanjutnya, kita berikan
garis dengan method beriGaris(x,y).
private boolean cek(int x, int y)
{
return (x>=0 && x<8 && y>=0 && y<8);
}
Method cek ini digunakan untuk mengecek apakah letak koordinat kotak masih berada pada
interface yang ditentukan (8x8). Method akan selalu menghasilkan nilai “true” selama nilai x lebih besar
dari atau sama dengan 0 dan kurang dari 8 dan selama nilai y lebih besar dari atau sama dengan 0 dan
kurang dari 8.
2 1 1 1 1 1 1 1
1 1 0 0 0 0 0 0
1 0 1 0 0 0 0 0
1 0 0 1 0 0 0 0
1 0 0 0 1 0 0 0
1 0 0 0 0 1 0 0
1 0 0 0 0 0 1 0
1 0 0 0 0 0 0 1
public boolean solve(int y) {
int i,j;
boolean r = false;
for (i=0;i<8;i++) {
if (kotak[i][y] == 0) {
taruhRatu(i,y,true);
if (y == 7) {
return true; // binggoH!!!
} else {
if (solve(y+1)) {
return true; // binggoH !!!
} else {
taruhRatu(i,y,false); // ambil ratu
}
}
}
}
return false;
}
}
Method ini berfungsi untuk menghasilkan output yang benar dan optimal secara otomatis.
Pertama, kita deklarasikan variable i dan j sebagai integer dan variable r sebagai Boolean dengan nilai
awal “false”. Setelah itu, melalui perulangan, kita akan mencoba untuk meletakkan ratu di setiap baris.
Jika nilai kotak [i][y] sama dengan 0, kita panggil method taruhRatu dengan
memasukkan nilai i, y, dan hasil Boolean “true” untuk variable taruh. Jika y sama dengan 7, kita
kembalikan nilai “true” yang berarti masalah telah terpecahkan. Apabila nilai y belum mencapai
7, jika nilai dari solve(y+1) bernilai “true” kita kembalikan nilai “true” yang juga berarti masalah
telah terpecahkan.
Tetapi, jika nilai kotak [i][y] tidak sama dengan 0, kita panggil method taruhRatu dengan
memasukkan nilai i,y, dan hasil Boolean “false” untuk variable taruh yang juga berarti tidak bisa
menaruh ratu. Kita kembalikan nilai “false” yang berarti masalah tidak terpecahkan.
File RatuApplet.java
Karena pada program kali ini kita menggunakan Applet, maka perlu kita buat untuk menjalankan
program applet-nya. Berikut adalah coding dari Applet.
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
Pertama – tama,kita akan memanggil paket java.applet, java.awt dan java.awt.event. java.applet
digunakan untuk membuat applet agar program dapat berjalan pada HTML. Java.awt untuk membuat
tampilan dan membuat gambar dan java.awt.event digunakan sebagai penangan tombol.
public class RatuApplet extends Applet implements ActionListener
{
Button refresh = new Button("Refresh");
Bidang Bidang = new Bidang();
Button solve = new Button("Solve");
Setelah itu, kita kan mendeklarasikan class yang digunakan pada applet. Nama class-nya adalah
RatuApplet yang merupakan turunan dari class Applet yang telah ada sebelumnya pada paket java. Kita
juga menggunakan interface ActionListener pada button yang akan kita buat nanti untuk menentukan
apa yang akan terjadi ketika button ditekan. Setelah itu, kita membuat Button refresh yang terhubung
dengan variable objek refresh. Setelah itu, kita akan memanggil class Bidang yang ada pada program
Bidang.Setelah itu, kita juga membuat button solve yang terhubung dengan variable objek solve.
public void init()
{
setLayout(new BorderLayout());
add("Center",Bidang);
selanjutnya, kita membuat method init yang akan berjalan ketika program running. Pertama,
kita set tata letak dengan tampilan BorderLayout() yang menempatkan komponen berdasarkan arah
mata angin. Disini kita meletakkan class Bidang pada bagian tengah tampilan.
Panel panel = new Panel();
add("South",panel);//kemungkinan besar, defaultnya BorderLayout
panel.setLayout(new GridLayout(1,5));
panel.add(new Label(""));
panel.add(refresh);
panel.add(new Label(""));
panel.add(solve);
panel.add(new Label(""));
refresh.addActionListener(this);
solve.addActionListener(this);
}
Setelah itu, kita akan membuat panel baru yang digunakan untuk tombol yang diletakkan di
bagian bawah(south) tampilan. Kemudian, kita tentukan tampilan panel dengan class GridLayout (yang
telah ada pada java) pada satu baris untuk membuat 5 kolomdengan ukuran yang sama yang akan kita
pergunakan untuk meletakkan button. Pada kolom pertama, kita isi dengan label kosong. Pada kolom
kedua kita isi dengan button refresh. Pada kolom ketiga kita isi dengan label kosong, pada kolom
keempat kita isi dengan button solve dan pada kolom kelima kita isi dengan label kosong lagi. Setelah
membuat tampilan, kita aplikasikan method ActionListener sebagai penangan kejadian pada tombol
refresh dan solve.
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource()==refresh)
{
Bidang.initBidang();
Bidang.paint(Bidang.getGraphics());
}else if (ae.getSource() == solve) {
Bidang.initBidang();
Bidang.paint(Bidang.getGraphics());
Bidang.solve(0);
}
}
}
Setelah itu, kita implementasikan method bernama actionPerformed (yang telah ada pada java)
sebagai penentu kejadian ketika kedua tombol itu ditekan. Kemudian kita lakukan seleksi kondisi. Jika
tombol yang ditekan adalah refresh, maka kita akan memanggil method initBidang dan paint dari Bidang
yang juga berarti mulai dari awal. Tetapi jika tombol yang ditekan adalah solve, kita akan memanggil
method initBidang dan paint serta solve dari Bidang yang juga berarti kita mulai dari awal dan akan
meletakkan ratu secara otomatis.