Saturday, December 24, 2016

Bab 5. Visual Basic .NET Belajar Dari Contoh


5. Prosedur







Pengantar

Program Visual Basic memuat banyak komponen, termasuk modul dan kelas. Programer mengkombinasikan modul dan kelas baru dengan kelas-kelas yang tersedia dalam FCL (Framework Class Library) .NET. Ketika prosedur dimuat di dalam sebuah kelas, prosedur tersebut dinamakan dengan metode.

FCL memuat koleksi yang kaya akan kelas dan metode yang bisa dipakai untuk melakukan kalkulasi matematik, manipulasi string, manipulasi karakter, operasi masukan/keluaran, pemeriksaan error, dan banyak operasi lain. Framework tersebut membuat pekerjaan programer menjadi lebih mudah, karena banyak metode di dalamnya menyediakan kapabilitas yang dibutuhkan. Pada beberapa bab terdahulu, pada Anda telah dikenalnya beberapa kelas FCL, seperti Console, yang menyediakan metode untuk membaca dan menampilkan data.

Meskipun FCL menyediakan banyak metode yang bisa dipakai untuk mengerjakan pekerjaan-pekerjaan yang umum dijumpai, tetap saja hal itu tidak bisa memenuhi semua yang dibutuhkan programer. Jadi, Visual Basic membolehkan programer untuk menciptakan prosedur yang bisa didefinisikan sendiri. Terdapat tiga tipe prosedur: prosedur Sub, prosedur Function, dan prosedur event. Pada bab ini, istilah prosedur akan merujuk pada prosedur Sub dan Function.


Prosedur Sub
Semua program yang disajikan pada beberapa bab terdahulu masing-masing memuat sedikitnya satu definisi prosedur (yaitu, Main) yang memanggil metode FCL (seperti Console.Write) untuk melakukan pekerjaan yang diinginkan. Sekarang, akan dibahas bagaimana menulis prosedur sendiri.

Perhatikan aplikasi konsol pada kode 5.1, yang menggunakan sebuah prosedur Sub (dipanggil dari prosedur Main) untuk menampilkan informasi gaji seorang karyawan.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
' Kode 5.1: Penggajian.vb
' Prosedur Sub untuk menampilkan informasi gaji.

Module modPenggajian

    Sub Main()

        ' memanggil prosedur Sub TampilGaji sebanyak 4 kali
        TampilGaji(40, 10.5)
        TampilGaji(38, 21.75)
        TampilGaji(20, 13)
        TampilGaji(50, 14)

    End Sub ' Main

    ' menampilkan gaji pada command window
    Sub TampilGaji(ByVal jam As Double, ByVal upah As Decimal)

        ' gaji = jam * upah
        Console.WriteLine("Gaji Anda adalah {0}", jam * upah)
    End Sub ' TampilGaji

End Module ' modPenggajian
Gaji Anda adalah 420
Gaji Anda adalah 826.5
Gaji Anda adalah 260
Gaji Anda adalah 700

Program memuat dua definisi prosedur. Baris 6-14 mendefinisikan prosedur Sub Main, yang dieksekusi ketika aplikasi konsol dijalankan. Baris 17-21 mendefinisikan prosedur Sub TampilGaji, yang dieksekusi ketika dipanggil dari prosedur lain, pada kasus ini Main.

Main melakukan empat pemanggilan (baris 9-12) terhadap prosedur Sub TampilGaji, menyebabkan TampilGaji dieksekusi sebanyak empat kali. Meskipun semua argumen prosedur pada contoh ini adalah konstanta, argumen sebenarnya dapat berupa variabel atau ekspresi. Sebagai contoh, statemen

TampilGaji(satuJamLembur, upaGajiJamLembur * 1.5)

dapat digunakan untuk menampilkan informasi gaji bagi seorang karyawan yang dibayar berdasarkan jumlah jam lembur.

Ketika Main memanggil TampilGaji, program membuat salinan dari tiap argumen (misalnya, 40 da 10.5 pada baris 9), dan kendali program beralih ke baris pertama pada prosedur TampilGaji. Prosedur TampilGaji menerima salinan dari kedua nilai tersebut dan menyimpannya di dalam dua variabel parameter jam dan upah. Kemudian, TampilGaji menghitung jam*upah dan menampilkan hasilnya (baris 20). Ketika statemen End Sub pada baris 21 dijumpai, kendali program beralih kembali ke prosedur pemanggil, pada kasus ini Main.

Baris pertama pada TampilGaji (baris 17) menunjukkan (di dalam kurung) bahwa TampilGaji mendeklarasikan sebuah variabel Double, jam, dan sebuah variabel Decimal, upah. Keduanya menampung nilai-nilai yang dilewatkan kepada TampilGaji di dalam definisi prosedur. Perhatikan bahwa keseluruhan definisi prosedur pada TampilGaji berada di dalam tubuh module modPenggajian. Semua prosedur harus didefinisikan di dalam sebuah module atau sebuah kelas. Format suatu definisi prosedur adalah

Sub nama-prosedur (daftar-parameter)
    deklarasi dan statemen
End Sub

Baris pertama kadangkala dipanggil dengan header prosedur. nama-prosedur, yang secara langsung ditempatkan setelah katakunci Sub pada header prosedur, dapat berupa sembarang pengenal valid dan dipakai untuk memanggil prosedur Sub ini di dalam program.
daftar-parameter merupakan daftar yang dipisahkan dengan koma, dimana di dalamnya prosedur Sub mendeklarasikan tipe dan nama tiap variabel parameter. Hanya satu argumen pada pemanggilan prosedur untuk tiap parameter pada header prosedur (meski ada pengecualian pada aturan ini yang akan ditunjukkan nanti). Argumen harus kompatibel dengan tipe parameter. Sebagai contoh, sebuah parameter bertipe Double dapat menerima nilai, seperti 7.35, 22, atau -32.343, tetapi tidak bisa menerima “siantar”, karena nilai Double tidak bisa memuat String. Jika sebuah prosedur tidak menerima sembarang nilai, daftar parameter dibuat kosong ( yaitu, nama prosedur diikuti dengan kurung kosong).

Perhatikan bahwa deklarasi parameter pada header prosedur TampilGaji (baris 17) tampak sama dengan deklarasi variabel, kecuali pada penggunaan katakunci ByVal (bukan Dim). Katakunci ByVal menspesifikasi bahwa pemanggilan program harus melewatkan salinan dari nilai argumen, yang digunakan pada tubuh prosedur Sub.

Deklarasi dan statemen pada definisi prosedur membentuk tubuh prosedur. Tubuh prosedur memuat kode Visual Basic untuk melakukan aksi-aski yang diinginkan. Tubuh prosedur harus diakhiri dengan katakunci End Sub, yang mendefinisikan akhir dari prosedur. Tubuh prosedur juga dikenal dengan blok. Sebuah blok merupakan rangkaian statemen dan deklarasi yang dikelompokkan bersama sebagai tubuh struktur tertentu dan diakhiri dengan statemen End, Next, Else, atau Loop tergantung dari jenis strukturnya. Variabel dapat dideklarasikan di dalam sembarang blok, dan blok dapat dibuat bersarang di dalam blok lain.

Kendali program akan beralih kembali ke pemanggil ketika eksekusi meraih statemen End Sub (akhir dari tubuh prosedur).


Prosedur Function
Prosedur Function sama dengan prosedur Sub, dengan satu perbedaan penting: prosedur Function menghasilkan nilai balik (yang dikirimkan) kepada pemanggil, sedangkan prosedur Sub tidak menghasilkan nilai balik apapun. Aplikasi konsol pada kode 5.2 menggunakan prosedur Function Kuadrat untuk menghitung kuadrat atas Integer dari 1 sampai 10.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
' Kode 5.2: KuadratInteger.vb
' Prosedur Function untuk mengkuadratkan sebuah angka.

Module modKuadratInteger

    Sub Main()
        Dim i As Integer ' kounter

        Console.WriteLine("Angka" & vbTab & "Kuadrat" & vbCrLf)

        ' mengkuadratkan angka dari 1 sampai 10
        For i = 1 To 10
            Console.WriteLine(i & vbTab & Kuadrat(i))
        Next

    End Sub ' Main

    ' Fungsi Kuadrat dieksekusi
    ' hanya ketika fungsi ini dipanggil secara eksplisit.
    Function Kuadrat(ByVal y As Integer) As Integer
        Return y ^ 2
    End Function ' Kuadrat

End Module ' modKuadratInteger
Angka   Kuadrat

1       1
2       4
3       9
4       16
5       25
6       36
7       49
8       64
9       81
10      100

Struktur For (baris 12-14) menampilkan hasil pengkuadratan atas Integer dari 1 sampai 10. Setiap iterasi pada loop menghitung kuadrat atas variabel kendali i dan menampilkannya pada command window.

Prosedur Function Kuadrat dipanggil (baris 13) dengan ekspresi Kuadrat(i). Ketika kendali program mencapai ekspresi ini, program memanggil Function Kuadrat (baris 20-22). Pada titik ini, program membuat salinan dari nilai i (argumen), dan kendali program beralih ke baris pertama pada Function Kuadrat. Kemudian Kuadrat menerima salinan dari nilai i dan menyimpannya di dalam parameter y. Baris 21 merupakan statemen Return, yang menghentikan eksekusi atas prosedur dan menghasilkan nilai balik y^2 kepada pemanggil. Hasilnya dijadikan nilai balik pada baris 13 dimana Kuadrat dipanggil. Baris 13 menampilkan nilai i dan nilai yang dijadikan nilai balik oleh Kuadrat pada command window. Proses ini diulangi sebanyak 10 kali.

Format suatu definisi prosedur Function adalah

Function nama-prosedur (daftar-parameter) As tipe-nilai-balik
    deklarasi dan statemen
End Function

nama-prosedur, daftar-parameter, dan deklarasi dan statemen pada sebuah definisi prosedur Function berperan seperti elemen-elemen pada definisi prosedur Sub. Pada header Function, tipe-nilai-balik mengindikasikan tipe data dari hasil yang dijadikan nilai balik oleh Function kepada pemanggilnya. Statemen

Return ekspresi

dapat terjadi dimana saja di dalam tubuh prosedur Function dan menghasilkan nilai dari ekspresi kepada pemanggil. Jika diperlukan, Visual Basic dapat mengkonversi ekspresi menjadi tipe-nilai-balik prosedur Function. Ketika statemen Return dieksekusi, kendali program kembali  ke titik dimana prosedur dipanggil.



Metode
Metode adalah sembarang prosedur yang dimuat di dalam sebuah kelas. Anda telah melihat beberapa metode FCL pada buku ini. Programer dapat mendefinisikan metode sendiri di dalam kelas yang didefinisikan sendiri, seperti sebuah kelas yang digunakan untuk mendefinisikan aplikasi Windows. Aplikasi Windows pada kode 5.3 menggunakan dua metode untuk mencari nilai terbesar dari tiga Double.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
' Kode 5.3: Maksimum.vb
' Program mencari nilai maksimum dari tiga masukan angka.

Public Class FrmMaksimum
    Inherits System.Windows.Forms.Form

    ' meminta tiga masukan
    Friend WithEvents lblSatu As System.Windows.Forms.Label
    Friend WithEvents lblDua As System.Windows.Forms.Label
    Friend WithEvents lblTiga As System.Windows.Forms.Label

    ' menampilkan hasil
    Friend WithEvents lblMaksimum As System.Windows.Forms.Label

    ' membaca tiga angka
    Friend WithEvents txtPertama As System.Windows.Forms.TextBox
    Friend WithEvents txtKedua As System.Windows.Forms.TextBox
    Friend WithEvents txtKetiga As System.Windows.Forms.TextBox

    ' membaca masukan dan menghitung hasil
    Friend WithEvents cmdMaksimum As System.Windows.Forms.Button

    ' kode yang dihasilkan IDE Visual Studio .NET

    ‘ mendapatkan nilai-nilai pada tiap kotak teks, memanggil prosedur Maksimum
    Private Sub cmdMaksimum_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles cmdMaksimum.Click
       
        Dim nilai1, nilai2, nilai3 As Double

        nilai1 = txtPertama.Text
        nilai2 = txtKedua.Text
        nilai3 = txtKetiga.Text

        lblMaksimum.Text = Maksimum(nilai1, nilai2, nilai3)
    End Sub ' cmdMaksimum2_Click

    ' mencari maksimum dari tiga nilai parameter
    Function Maksimum(ByVal nilaiSatu As Double, _
        ByVal nilaiDua As Double, ByVal nilaiTiga As Double)

        Return Math.Max(Math.Max(nilaiSatu, nilaiDua), nilaiTiga)
    End Function ' Maksimum

End Class ' FrmMaksimum

Kelas FrmMaksimum menggunakan sebuah GUI yang memuat beberapa TextBox (txtPertama, txtKedua, dan txtKetiga) untuk masukan pengguna, sebuah Button (cmdMaksimum) untuk memanggil fungsi Maksimum, dan empat Label, termasuk lblMaksimum, yang menampilkan hasil. Anda menciptakan semua komponen tersebut secara visual, menggunakan Toolbox, dan mengubah tiap propertinya pada jendela Properties. Baris 7-21 merupakan deklarasi yang mengindikasikan nama setiap komponen. Meskipun semua kode tersebut sebenarnya dihasilkan oleh Visual Studio .NET, tetap ditampilkan untuk mengindikasikan objek-objek yang terlibat.



Gambar 5.1 Keluaran program pada kode 5.3


Baris 5 mengindikasikan bahwa kelas FrmMaksimum mewarisi kelas System.Windows.Forms.-Form. Ingat bahwa semua form mewarisi kelas System.Windows.Forms.Form. Sebuah kelas dapat mewarisi atribut dan watak (data dan metode) dari kelas lain jika kelas tersebut dispesifikasi di sebelah kanan katakunci inherits.  Masalah pewarisan akan dibahas pada Bab 8, Pemrograman Berorientasi Objek: Pewarisan.

FrmMaksimum memuat dua metode yang didefinisikan sendiri. Metode Maksimum (baris 39-43) mengambil tiga parameter Double dan menghasilkan nilai balik berupa parameter terbesar. Perhatikan bahwa definisi metode ini tampak seperti definisi sebuah prosedur Function pada suatu module. Program juga menyertakan metode cmdMaksimum_Click (baris 26-36). Ketika pengguna mengklik dua kali suatu komponen, seperti sebuah Button, pada mode Design, IDE akan menghasilkan sebuah metode untuk menangani event (event handler). Sebuah event merepresentasikan aksi pengguna, seperti pengklikan sebuah Button atau pengubahan suatu nilai. Event handler adalah sebuah metode yang dieksekusi (dipanggil) ketika event tertentu dipicu. Pada kasus ini, metode cmdMaksimum_Click menangani event dimana tombol cmdMaksimum diklik. Hal ini akan dijelaskan secara detil pada Bab 11, Konsep GUI: Bagian 1.

Ketika pengguna mengklik cmdMaksimum, prosedur cmdMaksimum_Click (baris 26-36) akan dieksekusi. Baris 31-33 mengambil nilai-nilai pada tiga TextBox, menggunakan properti Text. Nilai-nilai tersebut dikonversi secara implisit menjadi tipe Double dan menyimpannya pada nilai1, nilai2, dan nilai3.

Baris 35 memanggil metode Maksimum (baris 39-43) dengan argumen-argumen nilai1, nilai2, dan nilai3. Nilai-nilai argumen tersebut kemudian disimpan pada parameter nilaiSatu, nilaiDua, dan nilaiTiga di dalam metode Maksimum. Metode Maksimum menghasilkan nilai balik berupa hasil dari ekspresi pada baris 42, yang melakukan pemanggilan terhadap metode Max dari kelas Math. Metode Max menghasilkan nilai balik berupa nilai terbesar dari kedua argumen Double-nya, yang berarti bahwa perhitungan pada baris 42 pertama-tama membandingkan nilaiSatu dan nilaiDua, kemudian membandingkan nilai balik dari pemanggil tersebut dengan nilaiTiga. Pemanggil terhadap metode, seperti Math.Max, yang didefinisikan di dalam FCL, harus mencantumkan nama kelas dan operator dot (.) (disebut pula dengan operator akses anggota).

Visual Basic juga menyediakan fitur IntelliSense, yang menampilkan semua anggota pada sebuah kelas. Sebagai contoh, ketika programer mengetikkan operator dot setelah nama kelas, Math, pada Gambar 5.2, IntelliSense menyediakan daftar semua metode pada kelas Math. Kelas Math memuat pelbagai metode yang memampukan programer untuk melakukan berbagai perhitungan matematik.



Gambar 5.2 Fitur IntelliSense IDE Visual Studio, menampilkan semua metode pada sebuah kelas



Ketika kendali program kembali ke metode cmdMaksimum_Click, baris 35 menugaskan nilai balik yang dihasilkan Maksimum kepada lblMaksimum pada properti Text, yang menyebabkan-nya ditampilkan pada pengguna.

Beberapa motode pada kelas Math dicantumkan pada Gambar 5.3. Pada tabel, variabel x dan y keduanya bertipe Double; tetapi banyak metode juga menyediakan beberapa versi yang mengambil argumen bertipe data lain. Di samping itu, kelas Math juga mendefinisikan dua konstanta matematik: Math.PI dan Math.E. Konstanta Math.PI (3.14159265358979323846) pada kelas Math merupakan rasio keliling lingkaran terhadap diameternya. Konstanta Math.E (2.7182818284590452354) adalah nilai basis untuk logaritma natural (dihitung dengan metode Math.Log).


Promosi Argumen
Fitur penting pada definisi prosedur adalah pemaksaan argumen (memaksa argumen menjadi tipe data yang cocok sehingga dapat dilewatkan kepada sebuah prosedur). Visual Basic mendukung kedua konversi pelebaran dan penyempitan. Konversi pelewabaran terjadi ketika sebuah tipe dikonversi menjadi tipe lain tanpa terjadi kehilangan data, sedangkan konversi penyempitan terjadi ketika berpotensi terjadinya kehilangan data. Gambar 5.4 menyajikan beberapa konversi pelebaran yang didukung oleh Visual Basic.

Metode
Deskripsi
Contoh
Abs(x)



Ceiling(x)


Cos(x)


Exp(x)



Floor(x)


Log(x)



Max(x, y)



Min(x, y)



Pow(x, y)


Sin(x)


Sqrt(x)


Tan(x)
menghasilkan nilai absolut dari x



membulatkan x menjadi integer terkecil yang tidak kurang dari x

menghasilkan kosinus trigonometrik atas x (x dalam radian)

menghasilkan eksponensial



membulatkan x menjadi integer terbesar yang tidak lebih besar dari x

menghasilkan logaritma natural atas x (basis e)


menghasilkan nilai terbesar dari x dan y (yang juga mempunyai versi untuk tipe Single, Integer, dan Long)

menghasilkan nilai terkecil dari x dan y (yang juga mempunyai versi untuk tipe Single, Integer, dan Long)

menghitung x dipangkat dengan y


menghitung sinus trigonometrik atas x (x dalam radian)

menghasilkan akar kuadrat atas x


menghitung tangent trigonometrik atas x (x dalam radian)
Abs(23.7) adalah 23.7
Abs(0) adalah 0
Abs(-23.7) adalah 23.7

Ceiling(9.2) adalah 10.0
Ceiling(-9.8) adalah -9.0

Cos(0.0) adalah 1.0


Exp(1.0) secara pendekatan 2.71828182845905
Exp(2.0) secara pendekatan
7.38905609893065

Floor(9.2) adalah 9.0
Floor(-9.8) adalah -10.0

Log(2.7182818284590451)
secara pendekatan 1.0
Log(7.3890560989306504)
secara pendekatan 2.0

Max(2.3, 12.7) adalah 12.7
Max(-2.3, -12.7) adalah -2.3


Min(2.3, 12.7) adalah 2.3
Min(-2.3, -12.7) adalah -12.7


Pow(2.0, 7.0) adalah 128.0
Pow(9.0, .5) adalah 3.0

Sin(0.0) adalah 0.0


Sqrt(9.0) adalah 3.0
Sqrt(2.0) adalah 1.4142135623731

Tan(0.0) adalah 0.0

Gambar 5.3 Metode-metode pada kelas Math

Sebagai contoh, metode Sqrt pada kelas Math dapat dipanggil dengan sebuah argumen Integer, meskipun metode tersebut didefinisikan pada kelas Math untuk menerima argumen Double. Statemen

Console.Write(Math.Sqrt(4))

secara tepat mengevaluasi Math.Sqrt(4) dan menampilkan nilai 2. Visual Basic mempromosikan (mengkonversi) Integer (nilai 4) menjadi Double (nilai 4.0) sebelum nilai tersebut dilewatkan kepada Math.Sqrt. Pada kasus ini, nilai argumen tidak persis sama dengan tipe parameter dalam definisi metode, sehingga konversi pelebaran implisit dilakukan oleh Visual Basic untuk mengubah nliai tersebut menjadi tipe sesuai sebelum metode dipanggil. Visual Basic juga melakukan konversi penyempitan pada argumen-argumen yang dilewatkan kepada prosedur. Sebagai contoh, jika variabel String, angka, memuat nilai “4”, maka pemanggilan metode Math.Sqrt(angka) akan menghasilkan nilai 2. Namun, beberapa kasus konversi penyempitan bisa mengalami kegagalan, menyebabkan error runtime dan error logika. Sebagai contoh, jika angka memuat nilai “hallo”, maka pelewatannya sebagai argumen kepada metode Math.Sqrt akan menyebabkan error runtime.

Tipe
Tipe Konversi
Boolean

Byte

Char

Date

Decimal

Double

Integer

Long

Object

Short

Single

String
Object

Short, Integer, Long, Decimal, Single, Double atau Object

String atau Object

Object

Single, Double atau Object

Object

Long, Decimal, Single, Double atau Object

Decimal, Single, Double atau Object

tidak ada

Integer, Long, Decimal, Single, Double atau Object

Double atau Object

Object

Gambar 5.4 Konversi pelebaran


Promosi argumen tidak hanya bisa diterapkan terhadap nilai bertipe data primitif yang dilewatkan sebagai argumen kepada metode, tetapi juga terhadap ekspresi yang memuat nilai-nilai dari dua atau lebih tipe data. Ekspresi semacam itu disebut dengan ekspresi tipe-campuran. Pada ekspresi tipe-campuran, setiap nilai dipromosikan ke tipe data “tertinggi” di dalam ekspresi (yaitu, konversi pelebaran dilakukan sehingga semua nilai bertipe data sama). Sebagai contoh, jika angkaSingle bertipe Single dan angkaInteger bertipe Integer, ketika Visual Basic akan mengevaluasi ekspresi

angkaSingle + angkaInteger


maka nilai dari angkaInteger dikonversi menjadi tipe Single, kemudian ditambahkan pada angkaSingle, yang menghasilkan hasil bertipe Single.


Option Strict dan Konversi Tipe Data
Visual Basic menyediakan beberapa opsi dalam mengendalikan cara bagaimana kompiler menangani tipe data. Opsi tersebut dapat menolong programer untuk mengeliminasi error yang disebabkan oleh konversi penyempitan dan untuk menjadikan kode lebih tangguh dan aman. Opsi pertama adalah Option Explicit, yang ditetapkan On secara default, yang berarti bahwa hal itu dilakukan pada semua program Visual Basic sejauh ini. Option Explicit memaksa programer untuk mendeklarasikan secara eksplisit semua variabel sebelum digunakan pada program. Pemaksaan deklarasi eksplisit mengeliminasi error pengejaan dan semua error tak-terlihat yang bisa terjadi jika Option Explicit dinon-aktif-kan. Sebagai contoh, ketika Option Explicit ditetapkan Off, kompiler akan menerjemahkan nama variabel yang salah-eja sebagai deklarasi variabel baru, yang menciptakan error tak-terlihat dan sulit untuk didebug.

Opsi kedua, yang secara default ditetapkan Off, adalah Option Strict. Visual Basic menyediakan Option Strict sebagai cara untuk meningkatkan kejelasan program dan mereduksi waktu debugging. Ketika ditetapkan menjadi On, Option Strict menyebabkan kompiler untuk memeriksa semua konversi dan meminta programer untuk melakukan konversi eksplisit untuk semua konversi penyempitan (yang bisa menyebabkan kehilangan data, seperti konversi Double menjadi Integer atau yang bisa menyebabkan program terhenti, seperti konversi String menjadi Integer).




Gambar 5.5 Dialog Property Pages dengan Option Strict ditetapkan menjadi On


Semua metode pada kelas Convert mengubah tipe data secara eksplisit. Nama setiap metode konversi diawali dengan kata To, diikuti dengan nama tipe data target. Sebagai contoh, untuk menyimpan masukan pengguna bertipe String di dalam variabel angka bertipe Integer (yang direpresentasikan dalam Visual Basic .NET sebagai tipe Int32, integer 32-bit) dengan Option Strict ditetapkan On, digunakan statemen

angka = Convert.ToInt32(Console.ReadLine())

Ketika Option Strict ditetapkan menjadi Off, Visual Basic melakukan konversi semacam itu secara implisit, berarti bahwa programer bisa jadi tidak menyadari bahwa sebuah konversi penyempitan sedang terjadi. Jika data yang sedang dikonversi tidak kompatibel dengan tipe data target, maka error runtime akan terjadi.

Mulai dari titik ini, semua contoh kode pada buku ini akan menetapkan On terhadap Option Strict. Option Strict dapat diaktivasi melalui IDE dengan mengklik-kanan nama project pada Solution Explorer. Dari menu yang dihasilkan, dipilih Properties untuk membuka dialog Property Pages, yang ditunjukkan pada Gambar 5.5. Kemudian pilih Compile, dan tetapkan On terhadap Option Strict.


Tipe Nilai dan Tipe Referensi
Pda bagian berikutnya, akan didiskusikan pelewatan argumen kepada prosedur dengan nilai dan dengan referensi. Untuk memahaminya, terlebih dahulu akan dijelaskan perbedaan antar tipe data pada Visual Basic. Semua tipe data Visual Basic dapat dikategorikan sebagai tipe nilai atau tipe referensi. Variabel betipe nilai memuat nilai dari tipe tersebut, seperti nilai Integer atau Double. Sebaliknya, variabel bertipe referensi memuat lokasi dalam memori dimana data disimpan. Secara kolektif, tipe referensi dikenal sebagai objek dan akan didiskusikan pada Bab 7, 8, dan 9.

Tipe
Ukuran
dalam
bit
Nilai
Standar
Boolean

Char

Byte

Date


Decimal

Short

Integer


Long


Single

Double

Object

String
16

16

8

64


128

16

32


64


32

64

32
True atau False

Satu karakter Unicode

0 sampai 255

1 Januari 0001 sampai 21 Desember 9999, 0:00:00 sampai 23:59:59

1.0E-28 sampai 7.9E+28

–32,768 sampai 32,767

–2,147,483,648 sampai 2,147,483,647

–9,223,372,036,854,775,808
sampai 9,223,372,036,854,775,807

±1.5E-45 sampai ±3.4E+38

±5.0E–324 sampai ±1.7E+308

Data sembarang tipe

0 sampai ~2000000000 karakter Unicode


(Himpunan karakter Unicode)
















(IEEE 754 titik-mengambang)

(IEEE 754 titik-mengambang)



(Himpunan karakter Unicode)


Gambar 5.6 Semua tipe data primitif pada Visual Basic


Kedua tipe (tipe nilai dan tipe referensi) mencakup tipe built-in dan tipe yang diciptakan sendiri. Tipe nilai built-in mencakup tipe integral (Byte, Short, Integer, dan Long), tipe titik-mengambang (Single dan Double), dan tipe Boolean, Date, Decimal dan Char. Tipe referensi built-in mencakup tipe Object dan String (meskipun tipe String seringkali berperilaku seperti tipe nilai). Tipe nilai yang dapat diciptakan sendiri oleh programer mencakup tipe Structure dan Enum. Tipe referensi yang dapat diciptakan sendiri oleh programer mencakup kelas, antarmuka, dan delegate. Tipe-tipe yang didefinisikan sendiri oleh programer akan dibahas pada Bab 7, Bab 8, dan Bab 14.

Tabel pada Gambar 5.6 mencantumkan semua tipe primitif. Jika Option Explicit ditetapkan On, maka semua variabel harus memiliki tipe sebelum digunakan pada suatu program.

Tipe
Karakter Tipe
Contoh
Char

Single

Double

Decimal

Short

Integer

Long

c

F

R

D

S

I

L
"u"c

9.802E+31F

6.04E-187R

128309.76D

3420S

-867I

19235827493259374L

Gambar 5.7 Literal dengan karakter tipenya


Sembarang nilai yang secara langsung diketikan pada kode program disebut dengan literal. Setiap literal terkait dengan salah satu tipe data primitif. Anda telah melihat literal, seperti bertipe String, Integer, Double. Tetapi, beberapa tipe data Visual Basic menggunakan notasi khusus dalam menciptakan literal. Sebagai contoh, untuk menciptakan sebuah literal bertipe Char, String karakter-tunggal ditempatkan sebelum karakter tipe c. Statemen

Dim karakter As Char = "Z"c

mendeklarasikan variabel karakter bertipe Char dan menginisialisasinya dengan karaketer “Z”. Sama halnya, literal untuk tipe data integral dapat diciptakan dengan menempatkan sebuah integer sebelum karakter tipe S (untuk Short), I (untuk Integer), atau L (untuk Long). Untuk menciptakan literal titik-mengambang, sebuah angka titik-mengambang ditempatkan sebelum karakter tipe F (untuk Single) atau R (untuk Double). Karakter tipe D dapat dipakai untuk menciptakan literal Decimal.

Visual Basic juga membolehkan programer untuk mengetikkan literal titik-mengambang dalam notasi saintifik, dengan menempatkan sebuah angka titik-mengambang sebelum karaketer E dan eksponen positif atau negatif. Sebagai contoh, 1.909E-5 berkaitan dengan nilai 0.00001909. Notasi ini berguna untuk merepresentasikan nilai titik-mengambang yang terlalu besar atau terlalu kecil untuk ditulis dalam notasi titik-tetap.

Gambar 5.7 menampilkan semua karakter tipe Visual Basic dan tiap contoh literal untuk tiap tipe data. Semua literal harus berada dalam rentang tipe literal, yang ditunjukkan pada Gambar 5.6.


Pelewatan Argumen: Pelewatan-dengan-Nilai vs. Pelewatan-dengan-Referensi
Argumen dapat dilewatkan dengan salah satu dari dua cara: Pelewatan-dengan-nilai dan pelewatan-dengan-referensi (juga dikenal dengan pemanggilan-dengan-nilai dan pemanggilan-dengan-referensi). Ketika argumen dilewatkan dengan nilai, program membuat salinan dari nilai argumen dan melewatkan salinan tersebut kepada prosedur yang dipanggil. Dengan pelewatan-dengan-nilai, perubahan terhadap salinan pada prosedur terpanggil tidak mempengaruhi nilai variabel asli. Sebaliknya, ketika argumen dilewatkan dengan referensi, pemanggil memberikan hak kepada prosedur terpanggil untuk mengakses dan memodifikasi data asli pemanggil secara langsung. Kode 5.4 mendemonstrasikan pelewatan argumen tipe-nilai dengan nilai dan dengan referensi.

Program melewatkan tiga variabel tipe-nilai, angka1, angka2, dan angka3, dengan beberapa cara berbeda kepada prosedur KuadratDgnNilai (baris 39-45) dan KuadratDgnReferensi (baris 48-54). Katakunci ByVal dalam header prosedur pada KuadratDgnNilai (baris 39) mengindikasikan bahwa argumen tipe-nilai harus dilewatkan dengan nilai. Ketika angka1 dilewatkan kepada KuadratDgnNilai (baris 13), salinan dari nilai yang disimpan di dalam angka1 (yaitu, 2) dilewatkan kepada prosedur. Oleh karena itu, nilai dari angka1 dalam prosedur pemanggil, Main, tidak termodifikasi ketika parameter angka dikuadratkan di dalam prosedur KuadratDgnNilai (baris 42).

Prosedur KuadratDgnReferensi menggunakan katakunci ByRef (baris 48) untuk menerima parameter tipe-nilai dengan referensi. Ketika Main memanggil KuadratDgnReferensi (baris 23), sebuah referensi yang menunjuk ke nilai yang disimpan di dalam angka2 dilewatkan, sehingga memberikan hak pada KuadratDgnReferensi untuk mengakses nilai yang disimpan dalam variabel asli. Jadi, nilai yang disimpan di dalam angka2, setelah KuadratDgnReferensi selesai dieksekusi, sama dengan nilai akhir dari parameter angka.

Jika argumen diapit di dalam kurung, (), maka salinan dari nilai argumen dilewatkan kepada prosedur, meskipun header prosedur mencantumkan katakunci ByRef. Jadi, nilai dari angka3 tidak berubah setelah ia dilewatkan kepada KuadratDgnReferensi (baris 33).

Pelewatan argumen tipe-nilai dengan katakunci ByRef berguna ketika prosedur perlu mengubah argumen secara langsung. Namun, pelewatan dengan referensi dapat melemahkan keamanan kode, karena prosedur terpanggil dapat secara langsung memodifikasi data pemanggil.


Durasi Pengenal
Pada semua bab terdahulu, telah digunakan pelbagai pengenal untuk berbagai tujuan, termasuk sebagai nama variabel dan sebagai nama prosedur, module, dan kelas. Setiap pengenal memiliki atribut tertentu, termasuk durasi dan skop.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
' Kode 5.4: UjiDgnRef.vb
' Demonstrasi pelewatan dengan nilai.

Module modUjiDgnRef

    ' mengkuadratkan tiga nilai ByVal dan ByRef, menampilkan hasil
    Sub Main()
        Dim angka1 As Integer = 2

        Console.WriteLine("Pelewatan argumen tipe-nilai dengan nilai:")
        Console.WriteLine("Sebelum pemanggilan KuadratDgnNilai, " & _
            "angka1 adalah {0}", angka1)
        KuadratDgnNilai(angka1) ' melewatkan angka1 dengan nilai
        Console.WriteLine("Setelah pemanggilan KuadratDgnNilai, " & _
            "angka1 adalah {0}" & vbCrLf, angka1)

        Dim angka2 As Integer = 2

        Console.WriteLine("Pelewatan argumen tipe-nilai" & _
            " dengan referensi:")
        Console.WriteLine("Sebelum pemanggil KuadratDgnReferensi, " & _
            "angka2 adalah {0}", angka2)
        KuadratDgnReferensi(angka2) ' melewatkan angka2 dengan referensi
        Console.WriteLine("Setelah pemanggilan " & _
        "KuadratDgnReferensi, angka2 adalah {0}" & vbCrLf, angka2)

        Dim angka3 As Integer = 2

        Console.WriteLine("Pelewatan argumen tipe-nilai" & _
            " dengan referensi, tetapi di dalam kurung:")
        Console.WriteLine("Sebelum pemanggil KuadratDgnReferensi " & _
            "menggunakan kurung, angka3 adalah {0}", angka3)
        KuadratDgnReferensi((angka3)) ' melewatkan angk3 dengan nilai
        Console.WriteLine("Setelah pemanggilan " & _
            "KuadratDgnReferensi, angka3 adalah {0}", angka3)

    End Sub ' Main

    ' mengkuadratkan angka dengan nilai (perhatikan katakunci ByVal)
    Sub KuadratDgnNilai(ByVal angka As Integer)
        Console.WriteLine("Setelah memasuki KuadratDgnNilai, " & _
            "angka adalah {0}", angka)
        angka *= angka
        Console.WriteLine("Sebelum keluar KuadratDgnNilai, " & _
            "angka adalah {0}", angka)
    End Sub ' KuadratDgnNilai

    ' mengkuadratkan angka dengan referensi (perhatikan katakunci ByRef)
    Sub KuadratDgnReferensi(ByRef angka As Integer)
        Console.WriteLine("Setelah memasuki KuadratDgnReferensi" & _
            ", angka adalah {0}", angka)
        angka *= angka
        Console.WriteLine("Sebelum keluar KuadratDgnReferensi" & _
            ", angka adalah {0}", angka)
    End Sub ' KuadratDgnReferensi

End Module ' modUjiDgnRef
Pelewatan argumen tipe-nilai dengan nilai:
Sebelum pemanggilan KuadratDgnNilai, angka1 adalah 2
Setelah memasuki KuadratDgnNilai, angka adalah 2
Sebelum keluar KuadratDgnNilai, angka adalah 4
Setelah pemanggilan KuadratDgnNilai, angka1 adalah 2

Pelewatan argumen tipe-nilai dengan referensi:
Sebelum pemanggil KuadratDgnReferensi, angka2 adalah 2
Setelah memasuki KuadratDgnReferensi, angka adalah 2
Sebelum keluar KuadratDgnReferensi, angka adalah 4
Setelah pemanggilan KuadratDgnReferensi, angka2 adalah 4

Pelewatan argumen tipe-nilai dengan referensi, tetapi di dalam kurung:
Sebelum pemanggil KuadratDgnReferensi menggunakan kurung, angka3 adalah 2
Setelah memasuki KuadratDgnReferensi, angka adalah 2
Sebelum keluar KuadratDgnReferensi, angka adalah 4
Setelah pemanggilan KuadratDgnReferensi, angka3 adalah 2

Durasi suatu pengenal (juga dikenal dengan usia-hidup) merupakan periode selama pengenal eksis di dalam memori. Beberapa pengenal eksis sangat singkat, beberapa diciptakan dan dihancurkan secara berulang, dan sebagian lagi dipertahankan selama eksekusi sebuah program.

Skop suatu pengenal adalah porsi dari sebuah program dimana pengenal dapat direferensi. Beberapa pengenal dapat direferensi di keseluruhan program; lainnya hanya bisa direferensi dari porsi program terbatas (seperti di dalam sebuah prosedur).

Pengenal yang merepresentasikan variabel lokal dalam sebuah prosedur (parameter dan variabel yang dideklarasika di dalam tubuh prosedur) memiliki durasi otomatis. Variabel berdurasi otomatis diciptakan ketika kendali program memasuki prosedur dimana variabel tersebut dideklarasikan. Variabel berdurasi otomatis eksis selama prosedur aktif dan dihancurkan ketika kendali program keluar dari prosedur.

Variabel yang dideklarasikan di dalam sebuah module atau kelas, tetapi di luar sembarang definisi prosedur, eksis selama kelas atau module yang memuatnya masih terdapat di dalam memori. Variabel yang dideklarasikan di dalam suatu module eksis selama ekskusi program berlangsung. Secara default, variabel yang dideklarasikan di dalam suatu kelas, seperti kelas Form untuk aplikasi Windows, merupakan variabel instans.


Aturan Skop
Skop (kadakala dinamakan dengan skop deklarasi) dari suatu pengenal variabel, referensi atau prosedur adalah porsi program dimana ia dapat diakses. Skop yang mungkin bagi sebuah pengenal adalah skop kelas, skop module, skop namespace, dan skop blok.

Anggota suatu kelas memiliki skop kelas, yang berarti bahwa ia dapat dikenali (visibel) di dalam apa yang dinamakan dengan skop deklarasi kelas. Skop kelas berawal dari pengenal kelas yang ditempatkan setelah katakunci Class dan berakhir pada statemen End Class. Skop ini memampukan sebuah metode dari kelas tertentu untuk memanggil secara langsung semua anggota yang didefinisikan di dalam kelas tersebut dan untuk mengakses anggota-anggota yang diwarisi oleh kelas tersebut. Anggota sebuah kelas bersifat global bagi metode yang didefinisikan di dalam kelas tersebut. Ini berarti bahwa metode tersebut dapat secara langsung memodifikasi variabel instans dari kelas itu dan memanggil metode lain dari kelas tersebut.

Dalam Visual Basic .NET, pengenal yang dideklarasikan di dalam sebuah blok, seperti tubuh definisi prosedur atau tubuh struktur seleksi If/Then, memiliki skop blok. Skop blok berawal dari deklarasi pengenal dan berakhir pada statemen End pada blok tersebut (atau ekivalen, seperti Next). Variabel lokal pada sebuah prosedur memiliki skop blok. Parameter prosedur juga memiliki skop blok, karena ia dipandang sebagai variabel lokal di dalam prosedur. Sembarang blok dapat memuat deklarasi variabel.

Ketika blok bersarang di dalam tubuh sebuah prosedur, error akan dibangkitkan jika pengenal yang dideklarasikan di dalam blok sebelah luar memiliki nama sama dengan suatu pengenal yang dideklarasikan di dalam blok sebelah dalam. Namun, jika variabel lokal di dalam prosedur terpanggil memiliki nama sama dengan variabel yang memiliki skop kelas, seperti variabel instans, maka variabel skop kelas akan tersembunyi (tidak dikenali) sampai prosedur terpanggil selesai dieksekusi.

Variabel yang dideklarasikan di dalam sebuah module memiliki skop module, yang sama dengan skop kelas. Variabel yang dideklarasikan di dalam sebuah module dapat diakses oleh semua prosedur yang didefinisikan di dalam module tersebut. Skop module dan skop kelas kadangkala digeneralisir sebagai skop module. Seperti variabel skop kelas, variabel skop module tersembunyi (tidak bisa dikenali) ketika terdapat pengenal dengan nama sama sebagai variabel lokal.

Secara default, prosedur yang didefinisikan di dalam sebuah module memiliki skop namespace, yang secara umum berarti bahwa ia dapat diakses dengan suatu projek. Skop namespace berguna dalam projek yang memuat beberapa module dan kelas.

Program pada kode 5.5 mendemonstrasikan isu skop pada variabel instans dan variabel lokal. Variabel instans, nilai, dideklarasikan dan diinisialisasi dengan 1 pada baris 12. Seperti dijelaskan sebelumnya, variabel ini tersembunyi (tidak dikenali) di dalam sembarang prosedur yang mendeklarasikan sebuah variabel bernama nilai. Metode FrmSkop_Load mendeklarasikan sebuah variabel lokal, nilai, (baris 19) dan menginisialisasinya dengan 5. Variabel ini ditampilkan pada lblOutput (perhatikan deklarasi pada baris 7, yang sebenarnya merupakan kode yang dibangkitkan oleh Visual Studio .NET) untuk mengilustrasikan bahwa variabel instans nilai tersembunyi di dalam  FrmSkop_Load.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
' Kode 5.5: Skop.vb
' Mendemonstrasikan aturan skop dan variabel instans.

Public Class FrmSkop
    Inherits System.Windows.Forms.Form

    Friend WithEvents lblOutput As System.Windows.Forms.Label

    ' kode yang dibangkitkan oleh Visual Studio .NET

    ' variabel instans dapat dipakai dimana saja di dalam kelas
    Dim nilai As Integer = 1

    ' mendemonstrasikan skop kelas dan skop blok
    Private Sub FrmSkop_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load

        ' variabel lokal untuk FrmSkop_Load menyembunyikan variabel instans
        Dim nilai As Integer = 5

        lblOutput.Text = "nilai variabel lokal di dalam" & _
            " FrmSkop_Load adalah " & nilai

        MetodeA() ' MetodeA memiliki nilai lokal otomatis
        MetodeB() ' MetodeB menggunakan nilai variabel instans
        MetodeA() ' MetodeA menciptakan nilai lokal otomatis yang baru
        MetodeB() ' nilai variabel instans mendapatkan nilainya

        lblOutput.Text &= vbCrLf & vbCrLf & "variabel lokal " & _
            "nilai di dalam FrmSkop_Load adalah " & nilai
    End Sub

    ' nilai variabel lokal menyembunyikan variabel instans
    Sub MetodeA()
        Dim nilai As Integer = 25 ' diinisialisasi pada tiap pemanggilan

        lblOutput.Text &= vbCrLf & vbCrLf & "variabel lokal " & _
            "nilai di dalam MetodeA adalah " & nilai & " setelah memasuki MetodeA"
        nilai += 1
        lblOutput.Text &= vbCrLf & "variabel lokal " & _
        "nilai di dalam MetodeA adalah " & nilai & " sebelum keluar dari MetodeA"
    End Sub ' MetodeA

    ' uses instance variable value
    Sub MetodeB()
        lblOutput.Text &= vbCrLf & vbCrLf & "variabel instans" & _
            " nilai adalah " & nilai & " setelah memasuki MetodeB"
        nilai *= 10
        lblOutput.Text &= vbCrLf & "variabel instans " & _
            "nilai adalah " & nilai & " sebelum keluar dari MetodeB"
    End Sub ' MetodeB

End Class



Gambar 5.8 Aturan skop pada sebuah kelas


Program mendefinisikan dua metode lain, MetodeA dan MetodeB, yang tidak memerlukan argumen dan tidak menghasilkan nilai balik apapun. Setiap metode dipanggil dua kali dari FrmSkop_Load. MetodeA mendefinisikan variabel lokal nilai (baris 35) dan menginisialisasinya dengan 25. Ketika MetodeA dipanggil, variabel ditampilkan di dalam label lblOutput, diinkremen dan ditampilkan kembali sebelum keluar dari metode tersebut. Variabel otomatis nilai dihancurkan ketika MetodeA berhenti. Jadi, setiap kali metode ini dipanggil, nilai diciptakan-ulang dan diinisialisasi-ulang dengan 25.

MetodeB tidak mendeklarasikan sembarang variabel. Oleh karena itu, ketika prosedur ini merujuk ke variabel nilai, variabel instans nilai (baris 12) lah yang digunakan. Ketika MetodeB dipanggil, varaibel instans ditampilkan, dikalikan dengan 10, dan ditampilkan kembali sebelum keluar dari metode tersebut. Pada pemanggilan MetodeB berikutnya, variabel instans mendapatkan kembali nilai termodifikasi, 10, dan baris 48 menyebabkan nilai (baris 12) menjadi 100. Terakhir, program menampilkan kembali variabel lokal nilai di dalam metode FrmSkop_Load untuk menunjukkan bahwa tidak ada pemanggilan metode yang memodifikasi variabel nilai tersebut.


Pembangkitan Bilangan Acak
Sekarang akan dibahas tentang pembuatan game. Akan dikembangkan sebuah program terstruktur  yang memuat beberapa metode. Program menggunakan beberapa kendali struktur yang telah dipelajari sejauh ini.

Elemen peluang diintroduksi melalui kelas Random (berada di dalam namespace System). Perhatikan dua statemen berikut:

Dim objekAcak As Random = New Random()
Dim angkaAcak As Integer = objekAcak.Next()

Statemen pertama mendeklarasikan objekAcak sebagai sebuah referensi yang menunjuk ke objek bertipe Random. Nilai dari objekAcak diinisialisasi menggunakan katakunci New, yang menciptakan sebuah instans baru dari kelas Random (objek Random).

Statemen kedua mendeklarasikan variabel Integer, angkaAcak, dan menugaskan nilai balik dari pemanggilan Next pada kelas Random kepadanya. Anda bisa mengakses metode Next dengan menempatkan nama referensi, objekAcak, sebelum operator dot dan nama metode. Metode Next menghasilkan nilai Integer positif antara nol dan konstanta Int32.MaxValue (2 147 483 647). Metode Next menghasilkan nilai acak, dimana masing-masing nilai berada di dalam rentang tersebut dan memiliki peluang yang sama. Nilai balik dari Next sebenarnya merupakan angka semi-acak, yang dihasilkan dengan perhitungan matematik kompleks. Perhitugan matematik ini memerlukan nilai tunas. Ketika Anda menciptakan sebuah objek Random, waktu sekarang menjadi nilai tunas. Namun, Anda juga dapat melewatkan suatu nilai tunas sebagai argumen yang diapit kurung dan ditempatkan setelah New Random.

Pembangkitan angka acak seringkali diperlukan di dalam sebuah program. Namun, rentang nilai yang dihasilkan oleh Next (nilai antara 0 sampai 2 147 483 647) seringkali berbeda dari yang diperlukan aplikasi tertentu. Sebagai contoh, sebuah program yang mensimulasikan pelemparan koin hanya memerlukan 0 untuk “kepala” dan 1 untuk “ekor”. Sebuah program yang mensimulasikan pelemparan dadu enam-sisi hanya memerlukan Integer acak dari 1 sampai 6.

Dengan melewatkan sebuah argumen kepada metode Next sebagai berikut

nilai = 1 + objekAcak.Next(6)

akan dihasilkan integer-integer dalam rentang 1-6. Ketika argumen tunggal dilewatkan kepada Next, nilai balik dari Next akan berada dalam rentang 0 sampai nilai dari argumen tersebut. Ini disebut dengan penskalaan. Angka 6 merupakan faktor skala. Anda bisa menggeser rentang yang dihasilkan dengan menambahkan 1 pada hasil sebelumnya, sehingga nilai yang dihasilkan berada dalam rentang 1 sampai 6, bukan 0 sampai 5. Nilai yang dihasilkan oleh Next selalu berada dalam rentang

x x + angkaAcak.Next(y) < y

Visual Basic menyederhakan proses ini dengan membolehkan programer untuk melewatkan dua argumen kepada Next. Sebagai contoh, statemen sebelumnya juga dapat dituliskan sebagai

nilai = objekAcak.Next(1, 7)

Perhatikan bahwa Anda perlu menggunakan 7 sebagai argumen kedua pada metode Next untuk menghasilkan integer-integer dalam rentang 1 sampai 6. Argumen pertama mengindikasikan nilai minimum di dalam rentang yang diinginkan, sedangkan argumen kedua sama dengan 1 + nilai maksimum yang diinginkan. Jadi, nilai-nilai yang dihasilkan oleh versi Next ini selalu berada dalam rentang

x objekAcak.Next(x, y) < y

Pada kasus ini, x adalah nilai penggeser, dan y-x adalah faktor skala. Kode 5.6 mendemonstrasikan kegunaan kelas Random dan metode Next dengan mensimulasikan 20 pelemparan atas sebuah dadu enam-sisi dan menampilkan nilai dari tiap pelemparan pada MessageBox. Perhatikan bahwa semua nilai berada di dalam rentang 1-6.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
' Kode 5.6: IntegerAcak.vb
' Membangkitkan bilangan acak.

Imports System.Windows.Forms

Module modIntegerAcak

    Sub Main()
        Dim objekAcak As Random = New Random()
        Dim angkaAcak As Integer
        Dim output As String = ""
        Dim i As Integer

        For i = 1 To 20
            angkaAcak = objekAcak.Next(1, 7)
            output &= angkaAcak & " "

            If i Mod 5 = 0 Then ' adalah kelipatan 5?
                output &= vbCrLf
            End If

        Next

        MessageBox.Show(output, "20 angka acak dari 1 sampai 6", _
            MessageBoxButtons.OK, MessageBoxIcon.Information)
    End Sub ' Main

End Module ' modIntegerAcak



Gambar 5.9 Integer-integer acak diciptakan dengan memanggil metode Next dari kelas Random


Program pada kode 5.7 menggunakan kelas Random untuk mensimulasikan pelemparan empat buah dadu enam-sisi. Kemudian digunakan beberapa fungsionalitas dari program ini di dalam contoh lain (kode 5.8) untuk mendemonstrasikan bahwa angka-angka yang dibangkitkan oleh Next terjadi dengan probabilitas yang sama.

Pada kode 5.7, digunakan metode penanganan-event cmdLempar_Click, yang dieksekusi manakala pengguna mengklik cmdLempat. Pemanggilan TampilDadu (baris 35-44) menyebabkan empat dadu tampak sedang dilempar setiap kali cmdLempar diklik. Perhatikan bahwa, ketika program ini dijalankan, citra-citra dadu tidak tampak sampai pengguna mengklik cmdLempar untuk pertama kalinya.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
' Kode 5.7: LemparDadu.vb
' Pelemparan empat dadu.

Imports System.IO

Public Class FrmLemparDadu
    Inherits System.Windows.Forms.Form

    ' tombol untuk melempar dadu
    Friend WithEvents cmdRoll As System.Windows.Forms.Button

    ' empat kotak gambar untuk menampilkan citra dadu
    Friend WithEvents lblDadu1 As System.Windows.Forms. PictureBox
    Friend WithEvents lblDadu2 As System.Windows.Forms. PictureBox
    Friend WithEvents lblDadu3 As System.Windows.Forms. PictureBox
    Friend WithEvents lblDadu4 As System.Windows.Forms. PictureBox

    ' kode yang dibangkitkan oleh Visual Studio .NET

    ' mendeklarasikan referensi objek Random
    Dim angkaAcak As Random = New Random()

    ‘ menampilkan hasil pelemparan empat dadu
    Private Sub cmdLempar_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles cmdLempar.Click

        ' metode secara acak menugaskan sebuah sisi kepada setiap dadu
        TampilDadu(lblDadu1)
        TampilDadu(lblDadu2)
        TampilDadu(lblDadu3)
        TampilDadu(lblDadu4)
    End Sub

    ' mendapatkan sebuah citra dadu acak
    Sub TampilDadu(ByVal lblDadu As PictureBox)

        ' membangkitkan integer acak dari 1 sampai 6
        Dim sisi As Integer = angkaAcak.Next(1, 7)

        ' mengambil citra terkait
        lblDadu.Image = Image.FromFile( _
            Directory.GetCurrentDirectory & "\Citra\dadu" & _
            sisi & ".png")
    End Sub ' TampilDadu

End Class

Metode TampilDadu menspesifikasi citra yang sesuai untuk nilai sisi yang dihitung dengan metode Next (baris 38). Perhatikan bahwa Anda mendeklarasikan objekAcak sebagai variabel instans dari FrmLemparDadu (baris 21). Ini membolehkan objek Random yang sama untuk digunakan setiap kali TampilDadu dieksekusi. Anda menggunakan properti Image (baris 41) untuk menampilkan sebuah citra pada label. Anda menetapkan nilai properti dengan statemen penugasan (baris 41-43). Perhatikan bahwa Anda menspesifikasi citra untuk ditampilkan menggunakan prosedur FromFile dari kelas Image (yang dimuat di dalam namespace System.Drawing). Metode Directory.Get-CurrentDirectory (yang dimuat di dalam namespace System.IO) menghasilkan nilai balik berupa lokasi folder dimana di dalamnya projek dilokasikan, termasuk bin, direktori yang memuat file-file projek terkompilasi. Citra dadu ditempatkan pada folder tersebut untuk kode 5.7 dan kode 5.8.

Perhatikan bahwa Anda perlu mencantumkan direktif Imports (baris 4) untuk menggunakan kelas-kelas di dalam System.IO, tetapi tidak untuk menggunakan kelas-kelas di dalam System.Drawing. Secara default, aplikasi Windows mengimpor beberapa namespace, termasuk Microsoft.Visual-Basic, System, System.Drawing, System.Windows.Form, dan System.Collections.

Aplikasi Windows pada kode 5.8 melempat 12 dadu untuk menunjukkan bahwa angka-angka yang dibangkitkan oleh kelas Random memiliki frekuensi yang hampir sama. Program menampilkan frekuensi kumulatif atas setiap sisi pada sebuah TextBox.



Gambar 5.10 Keluaran program pada kode 5.7


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

' Gambar 5.8: LemparDuaBelasDadu.vb
' Pelemparan 12 dadu dan tabel frekuensi.

Imports System.IO

Public Class FrmLemparDuaBelasDadu
    Inherits System.Windows.Forms.Form

    ' kotak gambar untuk menampilkan citra
    Friend WithEvents lblDadu1 As System.Windows.Forms.PictureBox
    Friend WithEvents lblDadu2 As System.Windows.Forms.PictureBox
    Friend WithEvents lblDadu3 As System.Windows.Forms.PictureBox
    Friend WithEvents lblDadu4 As System.Windows.Forms.PictureBox
    Friend WithEvents lblDadu5 As System.Windows.Forms.PictureBox
    Friend WithEvents lblDadu6 As System.Windows.Forms.PictureBox
    Friend WithEvents lblDadu7 As System.Windows.Forms.PictureBox
    Friend WithEvents lblDadu8 As System.Windows.Forms.PictureBox
    Friend WithEvents lblDadu9 As System.Windows.Forms.PictureBox
    Friend WithEvents lblDadu10 As System.Windows.Forms.PictureBox
    Friend WithEvents lblDadu11 As System.Windows.Forms.PictureBox
    Friend WithEvents lblDadu12 As System.Windows.Forms.PictureBox

    ' menampilkan semua frekuensi
    Friend WithEvents tampilTextBox As  _
        System.Windows.Forms.TextBox

    ' kode yang dibangkitkan oleh Visual Studio .NET

    ' deklarasi
    Dim objekAcak As Random = New Random()
    Dim satu, dua, tiga, empat, lima, enam As Integer

    Private Sub cmdLempar_Click _
        (ByVal sender As System.Object, _
         ByVal e As System.EventArgs) Handles cmdLempar.Click

        ' menugaskan sisi-sisi acak kepada 12 dadu menggunakan LemparDadu
        TampilDadu(lblDadu1)
        TampilDadu(lblDadu2)
        TampilDadu(lblDadu3)
        TampilDadu(lblDadu4)
        TampilDadu(lblDadu5)
        TampilDadu(lblDadu6)
        TampilDadu(lblDadu7)
        TampilDadu(lblDadu8)
        TampilDadu(lblDadu9)
        TampilDadu(lblDadu10)
        TampilDadu(lblDadu11)
        TampilDadu(lblDadu12)

        Dim total As Integer = satu + dua + tiga + empat + _
            lima + enam

        Dim output As String

        ' menampilkan frekuensi tiap sisi dadu
        output = "Sisi" & vbTab & vbTab & _
            "Frekuensi" & vbTab & vbTab & "Persen"

        output &= vbCrLf & "1" & vbTab & vbTab & satu & _
            vbTab & vbTab & String.Format("{0:P}", satu / total)

        output &= vbCrLf & "2" & vbTab & vbTab & dua & vbTab & _
            vbTab & String.Format("{0:P}", dua / total)

        output &= vbCrLf & "3" & vbTab & vbTab & tiga & vbTab & _
            vbTab & String.Format("{0:P}", tiga / total)

        output &= vbCrLf & "4" & vbTab & vbTab & empat & vbTab & _
            vbTab & String.Format("{0:P}", empat / total)

        output &= vbCrLf & "5" & vbTab & vbTab & lima & vbTab & _
            vbTab & String.Format("{0:P}", lima / total)

        output &= vbCrLf & "6" & vbTab & vbTab & enam & vbTab & _
            vbTab & String.Format("{0:P}", enam / total) & vbCrLf

        tampilTextBox.Text = output
    End Sub ' cmdLempar_Click

    ' menampilkan citra dadu tunggal
    Sub TampilDadu(ByVal labelDadu As PictureBox)

        Dim sisi As Integer = objekAcak.Next(1, 7)

        labelDadu.Image = _
        Image.FromFile(Directory.GetCurrentDirectory & _
            "\Citra\dadu" & sisi & ".png")

        ' menetapkan frekuensi sisi dadu
        Select Case sisi

            Case 1
                satu += 1

            Case 2
                dua += 1

            Case 3
                tiga += 1

            Case 4
                empat += 1

            Case 5
                lima += 1

            Case 6
                enam += 1

        End Select

    End Sub ' TampilDadu

End Class ' FrmLemparDuaBelasDadu
  


Gambar 5.11 Keluaran program pada kode 5.8


Contoh: Permainan Peluang
Salah satu permainan peluang yang populer adalah permaian dadu yang dikenal dengan “craps”, yang dimainkan di semua kasino. Aturan permainan ini sederhana:

Seorang pemain melempar dua dadu. Setiap dadu mempunyai enam sisi. Setiap sisi memuat 1, 2, 3, 4, 5, atau 6 spot. Setelah dadu berhenti (setelah dilempar), jumlah spot pada sisi samping (menghadap layar) dihitung. Jika hasil perjumlahan bernilai 7 atau 11 pada pelemparan pertama, maka pemain menang. Jika hasil perjumlahan bernilai 2, 3, atau 12 pada pelemparan pertama (disebut “craps”), maka pemain kalah. Jika hasil perjumlahan bernilai 4, 5, 6, 8, 9, atau 10 pada pelemparan pertama, maka penjumlahan tersebut menjadi poin bagi pemain. Untuk menang, pemain harus melanjutkan melempar dadu sampai pemain “mencetak poin”. Pemain kalah bila mendapatkan 7 sebelum ia mencetak poin.

Aplikasi pada kode 5.9 mensimulasikan permainan craps.

Perhatikan bahwa pemain harus melemparkan dua dadu pada tiap pelemparan. Ketika aplikasi dieksekusi, klik tombol Mainkan untuk memainkan permainan.

Baris 9-21 mengindikasikan bahwa program ini menggunakan kelas PictureBox, Label, Button, dan GroupBox dari namespace System.Windows.Forms. Meskipun Windows Form Designer menggunakan nama penuh untuk semua kelas ini (misalnya, System.Windows.Forms.Picture-Box), di sini hanya disebutkan nama kelas agar lebih sederhana. Nama kelas sudah cukup pada kasus ini, karena System.Windows.Forms diimpor secara default untuk aplikasi Windows.

Program ini mengintroduksi beberapa komponen GUI. Pertama, dinamakan GroupBox, merupakan kontainer yang dipakai untuk mengelompokkan beberapa komponen yang berelasi. Di dalam suatu GroupBox, ditambahkan dua PictureBox (komponen untuk menampilkan citra).

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

' Kode 5.9: PermainanCraps.vb
' Bermain permainan craps.

Imports System.IO

Public Class FrmPermainanCraps
    Inherits System.Windows.Forms.Form

    Friend WithEvents cmdLempar As Button ' melempar dadu
    Friend WithEvents cmdMain As Button ' mengawali permainan baru

    ' dadu ditampilkan setelah tiap pelemparan
    Friend WithEvents gbrDadu1 As PictureBox
    Friend WithEvents gbrDadu2 As PictureBox

    ' poinDaduGrup mengelompokkan dadu yang merepresentasikan poin pemain
    Friend WithEvents poinDaduGrup As GroupBox
    Friend WithEvents gbrPoinDadu1 As PictureBox
    Friend WithEvents gbrPoinDadu2 As PictureBox

    Friend WithEvents lblStatus As Label

    ‘ kode yang dibangkitkan oleh Visual Studio .NET

    ' konstanta-konstanta pelemparan-dadu
    Enum NamaDadu
        SNAKE_EYES = 2
        TREY = 3
        CRAPS = 7
        YO_LEVEN = 11
        BOX_CARS = 12
    End Enum

    ' nama-file dan konstanta direktori
    Const FILE_PREFIX As String = "/Citra/dadu"
    Const FILE_SUFFIX As String = ".png"

    Dim poinKu As Integer
    Dim daduKu1 As Integer
    Dim daduKu2 As Integer
    Dim objekAcak As Random = New Random()

    ‘ memulai permainan baru dan mendapatkan poin
    Private Sub cmdMainkan_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles cmdMainkan.Click

        ' menginisialisasi variabel-variabel untuk permainan baru
        poinKu = 0
        poinDaduGrup.Text = "Poin"
        lblStatus.Text = ""

        ' menghapus citra-citra dadu-poin
        gbrPoinDadu1.Image = Nothing
        gbrPoinDadu2.Image = Nothing

        Dim jum As Integer = LemparDadu()

        ' memeriksa pelemparan dadu
        Select Case jum

            Case NamaDadu.CRAPS, NamaDadu.YO_LEVEN

                ' menon-aktifkan tombol lempar
                cmdLempar.Enabled = False
                lblStatus.Text = "Anda Menang!!!"

            Case NamaDadu.SNAKE_EYES, _
                NamaDadu.TREY, NamaDadu.BOX_CARS

                cmdLempar.Enabled = False
                lblStatus.Text = "Maaf. Anda Kalah."

            Case Else
                poinKu = jum
                poinDaduGrup.Text = "Poin sebesar " & jum
                lblStatus.Text = "Lempar Kembali!"
                TampilDadu(gbrPoinDadu1, daduKu1)
                TampilDadu(gbrPoinDadu2, daduKu2)
                cmdMainkan.Enabled = False
                cmdLempar.Enabled = True

        End Select

    End Sub ' cmdMainkan_Click

    ‘ menentukan keluaran pelemparan berikutnya
    Private Sub cmdLempar_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles cmdLempar.Click

        Dim jum As Integer = LemparDadu()

        ' memeriksa keluaran pelemparan
        If jum = poinKu Then
            lblStatus.Text = "Anda Menang!!!"
            cmdLempar.Enabled = False
            cmdLempar.Enabled = True
        ElseIf jum = NamaDadu.CRAPS Then
            lblStatus.Text = "Maaf. Anda Kalah."
            cmdLempar.Enabled = False
            cmdMainkan.Enabled = True
        End If

    End Sub ' cmdLempar_Click

    ' menampilkan citra dadu
    Sub TampilDadu(ByVal gbrDadu As PictureBox, _
        ByVal sisi As Integer)

        ' menugaskan citra dadu pada kotak gambar
        gbrDadu.Image = _
            Image.FromFile(Directory.GetCurrentDirectory & _
            FILE_PREFIX & sisi & FILE_SUFFIX)
    End Sub ' TampilDadu

    ' membangkitkan lemparan dadu secara acak
    Function LemparDadu() As Integer
        Dim dadu1, dadu2 As Integer

        ' menentukan integer acak
        dadu1 = objekAcak.Next(1, 7)
        dadu2 = objekAcak.Next(1, 7)

        ' menampilkan pelemparan
        TampilDadu(gbrDadu1, dadu1)
        TampilDadu(gbrDadu2, dadu2)

        ' menetapkan nilai-nilai
        daduKu1 = dadu1
        daduKu2 = dadu2

        Return dadu1 + dadu2
    End Function ' LemparDadu

End Class

Sebelum mengintroduksi sembarang metode, program menyertakan beberapa deklarasi, termasuk Enum pada baris 26-32 dan pengenal Const pada baris 35-36. Pengenal Const dan Enum membantu agar program lebih mudah dibaca, dengan menyediakan pengenal deskriptif untuk angka atau String yang memiliki makna khusus. Pengenal Const dan Enum membantu programer untuk memastikan bahwa nilai-nilai tersebut konsisten pada program. Katakunci Const menciptakan sebuah pengenal konstanta tunggal; Enum dipakai untuk mendefinisikan sekelompok konstanta yang berelasi.  Pada kasus ini, diciptakan beberapa pengenal Const untuk nama-nama file yang digunakan pada program dan diciptakan sebuah Enum yang memuat beberapa nama deskriptif untuk berbagai kombinasi dadu dalam Craps (misalnya, SNAKE_EYES, TREY, CRAPS, YO_LEVEN, dan BOX_CARS). Pengenal Const harus ditugasi nilai konstan dan tidak dapat dimodifikasi setelah dideklarasikan.



Gambar 5.12 Keluaran program pada kode 5.9


Setelah deklarasi pengenal konstanta dan deklarasi beberapa variabel instans (baris 38-41), metode cmdMainkan_Click didefinisikan (baris 44-84). Metode cmdMainkan_Click merupakan event handler untuk event cmdMainkan_Click (yang diciptakan dengan klik ganda cmdMainkan pada mode Design). Pada contoh ini, tugas metode ini adalah untuk memproses interaksi pengguna dengan Button cmdMainkan (yang menampilkan teks Mainkan pada antarmuka pengguna).

Ketika pengguna mengklik tombol Mainkan, metode cmdMainkan_Click menetapkan sebuah permainan baru dengan menginisialisasi beberapa nilai (baris 48-50). Penetapan properti Image, gbrPoinDadu1 dan gbrPoinDadu2, menjadi Nothing (baris 53-54) menyebabkan PictureBox tidak menampilkan apapun. Katakunci Nothing dapat dipakai dengan variabel tipe-referensi untuk menentukan bahwa tidak ada objek yang diasosiasikan dengan variabel tersebut.

Metode cmdMainkan_Click dieksekusi dengan pemanggilan LemparDadu (baris 56). Secara internal, LemparDadu (baris 116-132) menghasilkan dua angka acak dan memanggil metode TampilDadu (baris 106-113).

Ketika LemparDadu selesai dieksekusi, struktur Select (baris 59-82) menganalisa pelemparan yang dihasilkan oleh LemparDadu untuk menentukan apakah permainan harus dilanjutkan atau tidak. Tergantung pada nilai lemparan, tombol cmdLempar dan cmdMainkan menjadi enabled atau disabled. Penon-aktif-an (disabling) Button menyebabkan tidak ada aksi yang dilakukan ketika Button diklik. Button dapat diaktifkan (enabled) dan di-non-aktif-kan (disabled) dengan mengatur properti Enabled menjadi True atau False.


Rekursi
Pada kebanyakan program yang telah didiskusikan sejauh ini, prosedur memanggil prosedur lainnya secara hirarkis. Namun, pada beberapa contoh, adalah memungkinkan untuk memampukan prosedur untuk memanggil dirinya sendiri. Prosedur rekursif adalah sebuah prosedur yang memanggil dirinya sendiri baik secara langsung maupun tak langsung. Rekursi merupakan topik penting yang didiskusikan pada beberapa matakuliah. Pada bagian ini dan bagian berikutnya, akan disajikan beberapa contoh rekursi sederhana.

Sebelum mendiskusikan program yang memuat prosedur rekursif, terlebih dahulu akan didiskusikan tentang rekursi secara konseptual. Prosedur rekursif dipanggil untuk menyelesaikan sebuah permasalahan. Prosedur tersebut hanya mengerti bagaimana menyelesaikan kasus tersederhana atau kasus basis. Jika prosedur dipanggil dengan sebuah kasus basis, prosedur tersebut akan memberikan hasil. Jika prosedur dipanggil dengan masalah yang lebih kompleks, prosedur akan membagi masalah menjadi dua bagian (submasalah) konseptual; sebuah bagian dimana prosedur mengetahui bagaimana menyelesaikannya (kasus basis), dan sebuah bagian lainnya dimana prosedur tidak mengetahui bagaimana menyelesaikannya.

Sebagai sebuah contoh untuk konsep ini, akan dituliskan sebuah program rekursif yang melakukan perhitungan matematik populer.

Faktorial dari sebuah integer tak-negatif n, ditulis dengan n! (dan dibaca “n faktorial”), merupakan perkalian atas

n · ( n - 1 ) · ( n - 2 ) · … · 1

dimana 1! sama dengan 1, dan 0! didefinisikan sebagai 1. Sebagai contoh, 5! merupakan perkalian atas 5 · 4 · 3 · 2 · 1, yang sama dengan 120.

Faktorial atas sebuah integer, angka, yang lebih besar dari atau sama dengan 0, dapat dihitung secara iteratif (tak-rekursif) menggunakan struktur repetisi For, sebagai berikut:

Dim kounter, faktorial As Integer = 1

For kounter = angka To 1 Step -1
    faktorial *= kounter
Next

Kemudian, definisi rekursif atas prosedur faktorial dapat direlasikan sebagai berikut:

n! = n · ( n - 1 )!

Sebagai contoh, 5! sama dengan 5 · 4!, seperti ditunjukkan berikut:

5! = 5 · 4 · 3 · 2 · 1
5! = 5 · ( 4 · 3 · 2 · 1 )
5! = 5 · ( 4! )

Evaluasi rekursif atas 5! ditunjukkan pada Gambar 5.13. Gambar 5.13a menunjukkan bagaimana prosesi pemanggilan rekursif dilakukan sampai 1! dievaluasi menjadi 1, yang menghentikan rekursi. Gambar 5.13b menunjukkan nilai-nilai yang dijadikan nilai balik dari setiap pemanggilan rekursif kepada pemanggilnya sampai nilai akhir dihitung.



Gambar 5.13 Evaluasi rekursif atas 5!


Program pada kode 5.10 secara rekursif menghitung dan menampilkan faktorial. (Pilihan atas tipe data Long akan dijelaskan nanti). Metode rekursif Faktorial (baris 33-41) terlebih dahulu diuji (baris 35) untuk menentukan apakah kondisi bernilai true (yaitu, angka lebih kecil dari atau sama dengan 1). Jika angka kurang dari atau sama dengan 1, maka Faktorial akan menghasilkan nilai balik 1, dan tidak ada lagi rekursi yang diperlukan. Jika angka lebih besar dari 1, maka baris 38 mengekspresikan masalah sebagai perkalian atas angka dengan pemanggilan rekursif terhadap Faktorial (angka – 1).  Perhatikan bahwa Faktorial(angka – 1) merupakan masalah yang lebih sederhana daripada Faktorial(angka).

Function Faktorial (baris 33) menerima sebuah parameter bertipe Long dan menghasilkan nilai balik bertipe Long. Seperti yang dapat dilihat pada keluaran program pada kode 5.10, nilai-nilai fakorial menjadi besar dengan sangat cepat. Tipe data Long dipilih agar program dapat menghitung faktorial yang lebih besar dari 12!. Tetapi sayangnya, nilai-nilai yang dihasilkan oleh metode Faktorial sangat cepat bertambah dengan laju dimana bahkan rentang tipe Long sangat cepat terlampaui. Hal ini merupakan kelemahan dari hampir semua bahasa pemrograman: Tidak bisa dihandalkan untuk menyelesaikan masalah yang rumit, seperti evaluasi terhadap faktorial yang besar. Seperti yang akan Anda lihat, pada Bab 7, Visual Basic menyediakan cara dalam menciptakan tipe data sendiri (dinamakan dengan kelas) agar bisa menyelesaikan masalah seperti ini.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
' Kode 5.10: Faktorial.vb
' Menghitung faktorial menggunakan rekursi.

Public Class FrmFaktorial
    Inherits System.Windows.Forms.Form

    Friend WithEvents lblEnter As Label ' meminta Integer
    Friend WithEvents lblFaktorial As Label ' indikasi keluaran

    Friend WithEvents txtMasukan As TextBox ' membaca Integer
    Friend WithEvents txtTampil As TextBox ' menampilkan keluaran

    Friend WithEvents cmdHitung As Button ' menghasilkan keluaran

    ' kode yang dihasilkan Visual Studio .NET

    Private Sub cmdHitung_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles cmdHitung.Click

        Dim nilai As Integer = Convert.ToInt32(txtMasukan.Text)
        Dim i As Integer
        Dim keluaran As String

        txtTampil.Text = ""

        For i = 0 To nilai
            txtTampil.Text &= i & "! = " & Faktorial(i) & vbCrLf
        Next

    End Sub 'cmdHitung_Click

    ' secara rekursif menghasilkan faktorial atas angka
    Function Faktorial(ByVal angka As Long) As Long

        If angka <= 1 Then ' kasus basis
            Return 1
        Else
            Return angka * Faktorial(angka - 1)
        End If

    End Function ' Faktorial

End Class  ‘FrmFaktorial




Gambar 5.14 Keluaran program pada kode 5.10


Contoh Menggunakan Rekursi: Deret Fibonacci
Deret Fibonacci

0, 1, 1, 2, 3, 5, 8, 13, 21, …

dimulai dengan 0 dan 1 dan mendefinisikan suku Fibonacci berikutnya sebagai penjumlahan dari dua suku Fibonacci sebelumnya.

Deret Fibonacci dapat didefinisikan secara rekursif sebagai berikut:

fibonacci( 0 ) = 0
fibonacci( 1 ) = 1
fibonacci( n ) = fibonacci( n – 1 ) + fibonacci( n – 2 )

Perhatikan bahwa ada dua kasus basis untuk perhitungan Fibonacci, yaitu fibonacci(0) yang didefinisikan 0 dan fibonacci(1) yang didefinisikan 1. Aplikasi pada kode 5.11 secara rekursif menghitung suku Fibonacci ke-i melalui metode Fibonacci. Pengguna memasukkan sebuah integer di dalam kotak teks, mengindikasikan suku Fibonacci ke-i yang ingin dihitung, dan mengklik cmdHitung. Metode cmdHitung_Click dieksekusi karena merespon pengklian tombol Hitung Fibonacci. Perhatikan bahwa suku-suku Fibonacci, seperti nilai-nilai faktorial, cenderung membesar sangat cepat. Oleh karena itu, digunakan tipe data Long sebagai tipe parameter dan sebagai nilai balik dari metode Fibonacci.

Penanganan event pada contoh ini sama dengan aplikasi Maksimum pada kode 5.3. Pada contoh ini, pengguna memasukkan sebuah nilai di dalam kotak teks dan mengklik Hitung Fibonacci, menyebabkan metode cmHitung_Click dieksekusi.

Pemanggilan terhadap Fibonacci (baris 23) dari cmdHitung_Click bukanlah pemanggilan rekursif, tetapi semua pemanggilan berikutnya terhadap Fibonacci (baris 33) adalah pemanggilan rekursif. Setiap kali Fibonacci dipanggil, ia menguji kasus basis, yang terjadi ketika angka sama dengan 0 atau 1 (baris 30). Jika kondisi ini bernilai true, maka angka dijadikan nilai balik, karena fibonacci(0) adalah 0 dan fibonacci(1) adalah 1. Yang menarik adalah jika angka lebih besar dari 1, maka langkah rekursi menghasilkan dua pemanggilan rekursif, masing-masing merepresentasikan permasahalan yang lebih sederhana daripada yang direpresentasikan oleh pemanggilan awal terhadap Fibonacci. Gambar 5.16 mengilustrasikan bagaimana metode Fibonacci mengevaluasi Fibonacci(3).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
' Kode 5.11: Fibonacci.vb
' Mendemonstrasikan runtun Fibonacci secara rekursif.

Public Class FrmFibonacci
    Inherits System.Windows.Forms.Form

    Friend WithEvents lblPrompt As Label ' meminta masukan
    Friend WithEvents lblHasil As Label ' menampilkan hasil

    Friend WithEvents cmdHitung As Button ' menghitung hasil

    Friend WithEvents txtKotakMasukan As TextBox ' membaca sebuah Integer

    ' kode yang dihasilkan Visual Studio .NET

    ' menampilkan suku Fibonacci di dalam txtKotakMasukan
    Private Sub cmdHitung_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles cmdHitung.Click

        ' membaca masukan
        Dim angka As Integer = Convert.ToInt32(txtKotakMasukan.Text)

        lblHasil.Text = "Nilai Fibonacci adalah " & Fibonacci(angka)
    End Sub

    ' menghitung nilai Fibonacci secara rekursif
    Function Fibonacci(ByVal angka As Integer) As Long

        ' memeriksa untuk kasus basis
        If angka = 1 OrElse angka = 0 Then
            Return angka
        Else
            Return Fibonacci(angka - 1) + Fibonacci(angka - 2)
        End If

    End Function ' Fibonacci

End Class  ‘FrmFibonacci

Yang perlu diingat dalam menggunakan program rekursif untuk membangkitkan suku-suku Fibonacci: Setiap pemanggilan terhadap metode Fibonacci yang tidak cocok dengan salah satu kelas basis (yaitu, 0 atau 1) akan menghasilkan dua pemanggilan rekursif terhadap metode Fibonacci. Hal ini dengan cepat menyebabkan ledakan pemanggilan secara eksponensial. Sebagai contoh, perhitungan atas suku Fibonacci ke-20 menggunakan program pada kode 5.11 memerlukan 21 891 pemanggilan terhadap metode Fibonacci; Perhitungan atas suku Fibonacci ke-30 memerlukan 2 692 537 pemanggilan terhadap metode Fibonacci.



Gambar 5.15 Keluaran program pada kode 5.11



Gambar 5.16 Semua pemanggilan terhadap Fibonacci

Jika program menguji suku-suku Fibonacci yang lebih besar, maka program akan memerlukan waktu yang cukup lama untuk memberikan hasil. Sebagai contoh, suku Fibonacci ke-31 memerlukan 4 356 617 pemanggilan, sedangkan suku Fibonacci ke-32 memerlukan 7 049 155 pemanggilan. Masalah rekursi ini menunjukkan bahwa komputer dengan prosesor paling mutakhir pun memerlukan waktu yang sangat lama dalam menghitung Fibonacci(50)!


Pengoverloadan Prosedur
Dengan pengoverloadan, programer dapat mendefinisikan beberapa prosedur dengan nama sama, sepanjang semua prosedur tersebut memiliki daftar parameter (sidik) yang berbeda (jumlah parameter, tipe parameter, atau urutan parameter). Ketika sebuah prosedur yang dioverload dipanggil, kompiler akan memilih prosedur yang sesuai dengan memeriksa jumlah, tipe, dan urutan argumen. Seringkali, pengoverloadan prosedur digunakan untuk menciptakan beberapa prosedur dengan nama sama tetapi dengan pekerjaan yang berbeda.

Program pada kode 5.12 menggunakan metode teroverload, Kuadrat, untuk menghitung kuadrat atas sebuah Integer dan sebuah Double.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
' Kode 5.12: Overload.vb
' Menggunakan metode-metode teroverloaded.

Public Class FrmOverload
    Inherits System.Windows.Forms.Form

    Friend WithEvents outputLabel As Label

    ' kode yang dibangkitkan oleh Visual Studio .NET

    Private Sub FrmOverload_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load

        outputLabel.Text = "Kuadrat atas Integer 7 adalah " & _
            Kuadrat(7) & vbCrLf & "Kuadrat atas Double " & _
            "7.5 adalah " & Kuadrat(7.5)
    End Sub

    Function Kuadrat(ByVal nilai As Integer) As Integer
        Return Convert.ToInt32(nilai ^ 2)
    End Function ' Kuadrat

    Function Kuadrat(ByVal nilai As Double) As Double
        Return nilai ^ 2
    End Function ' Kuadrat

End Class  ‘FrmOverload



Gambar 5.17 Keluaran dari program pada kode 5.12


Pada kode 5.12, kompiler menggunakan nama logis “Kuadrat atas Integer” untuk metode Kuadrat yang menspesifikasi sebuah parameter Integer (baris 19) dan “Kuadrat atas Double” untuk metode Kuadrat yang menspesifikasi sebuah parameter Double (baris 23).

Pada kode 5.13, terdapat dua prosedur teroverload dengan sidik (daftar parameter) identik tetapi dengan tipe nilai balik yang berbeda. Error yang diakibatkan ditunjukkan pada Gambar 5.18.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
' Kode 5.13: Overload.vb
' Menggunakan metode-metode teroverloaded.

Public Class FrmOverload
    Inherits System.Windows.Forms.Form

    Friend WithEvents outputLabel As Label

    ' kode yang dibangkitkan oleh Visual Studio .NET

    Private Sub FrmOverload_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load

        outputLabel.Text = "Kuadrat atas Integer 7 adalah " & _
            Kuadrat(7) & vbCrLf & "Kuadrat atas Double " & _
            "7.5 adalah " & Kuadrat(7.5)
    End Sub

    Function Kuadrat(ByVal nilai As Double) As Integer
        Return Convert.ToInt32(nilai ^ 2)
    End Function ' Kuadrat

    Function Kuadrat(ByVal nilai As Double) As Double
        Return nilai ^ 2
    End Function ' Kuadrat

End Class  ‘FrmOverload





Gambar 5.18 Error yang diakibatkan oleh program pada kode 5.13


Argumen Opsional
Visual Basic membolehkan programer untuk menciptakan prosedur yang mengambil satu atau lebih argumen opsional. Ketika sebuah parameter dideklarasikan sebagai opsional, pemanggil memiliki opsi dalam melewatkan argumen tertentu. Argumen opsional dispesifikasi pada header prosedur dengan katakunci Optional. Sebagai contoh, header prosedur

Sub ContohProsedur(ByVal nilai1 As Boolean, Optional _
    ByVal nilai2 As Long = 0)

menspesifikasi parameter terakhir sebagai Optional. Pemanggilan terhadap ContohProsedur harus melewatkan sedikitnya satu argumen, atau jika tidak, error sintaks akan dibangkitkan. Ini didemonstrasikan dengan beberapa pemanggilan berikut terhadap ContohProsedur:

ContohProsedur ()
ContohProsedur (True)
ContohProsedur (False, 10)

Pemanggilan pertama terhadap ContohProsedur membangkitkan error sintaks, karena minimum satu argumen diperlukan pada kasus ini. Pemanggilan kedua terhadap ContohProsedur valid karena satu argumen dilewatkan. Argumen Optional, nilai2, tidak dispesifikasi di dalam pemanggilan prosedur. Pemanggilan terakhir terhadap ContohProsedur juga valid: False dilewatkan sebagai satu argumen yang diperlukan, dan 10 dilewatkan sebagai argumen Optional.

Pada pemanggilan yang hanya melewatkan satu argumen (True) kepada ContohProsedur, nilai2 ditetapkan default 0, yang merupakan nilai yang dispesifikasi pada header prosedur. Argumen Optional harus menspesifikasi nilai default, menggunakan tanda sama dengan yang diikuti dengan nilai. Sebagai contoh, header untuk ContohProsedur menetapkan 0 sebagai nilai default untuk nilai2. Nilai default hanya dapat dipakai dengan parameter yang dideklarasikan Optional.

Contoh pada kode 5.14 mendemonstrasikan kegunaan dari argumen opsional. Program menghitung hasil pemangkatan basis dengan eksponen, yang keduanya ditentukan oleh pengguna. Jika pengguna tidak menentukan eksponen, argumen Optional diabaikan, dan nilai default 2 digunakan.

Baris 27 menentukan apakah txtPangkat memuat sebuah nilai. Jika ya, nilai di dalam TextBox dikonversi menjadi Integer dan dilewatkan pada Pangkat. Sebaliknya, nilai di dalam TextBasis dikonversi menjadi Integer dan dilewatkan sebagai argumen pertama kepada Pangkat pada baris 31. Argumen kedua, yang memiliki nilai 2, disediakan oleh kompiler Visual Basic, dan tidak terlihat oleh programer pada pemanggilan.

Metode Pangkat (baris 38-49) menspesifikasi bahwa argumen keduanya adalah Optional. Ketika diabaikan, argumen kedua ditetapkan default menjadi 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
' Kode 5.14: Pangkat.vb
' Menghitung pemangkatan basis dengan eksponen, eksponen default 2.

Public Class FrmPangkat
    Inherits System.Windows.Forms.Form

    Friend WithEvents txtBasis As TextBox ' membaca basis
    Friend WithEvents txtPangkat As TextBox ' membaca pangkat

    Friend WithEvents masukanGrup As GroupBox

    Friend WithEvents lblBasis As Label ' meminta basis
    Friend WithEvents lblPangkat As Label ' meminta pangkat
    Friend WithEvents lblKeluaran As Label ' menampilkan keluaran

    Friend WithEvents cmdHitung As Button ' menghasilkan keluaran

    ' kode yang dibangkitkan oleh Visual Studio .NET

    ' membaca masukan dan menampilkan hasil
    Private Sub cmdHitung_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles cmdHitung.Click

        Dim nilai As Integer

        ' memanggil versi Pangkat bergantung pada masukan pangkat
        If Not txtPangkat.Text = "" Then
            nilai = Pangkat(Convert.ToInt32(txtBasis.Text), _
            Convert.ToInt32(txtPangkat.Text))
        Else
            nilai = Pangkat(Convert.ToInt32(txtBasis.Text))
        End If

        lblKeluaran.Text = Convert.ToString(nilai)
    End Sub ' cmdHitung_Click

    ' menggunakan iterasi untuk menghitung pangkat
    Function Pangkat(ByVal basis As Integer, _
        Optional ByVal eksponen As Integer = 2) As Integer

        Dim total As Integer = 1
        Dim i As Integer

        For i = 1 To eksponen
            total *= basis
        Next

        Return total
    End Function ' Pangkat

End Class  ‘ FrmPangkat



Gambar 5.19 Keluaran program pada kode 5.14


Module
Programer menggunakan module untuk mengelompokkan beberapa prosedur yang berelasi sehingga dapat digunakan kembali pada projek lain. Dalam banyak hal, module sama dengan kelas; memampukan programer untuk membangun komponen yang dapat digunakan kembali. Penggunaan module dalam sebuah projek memerlukan pengetahuan tentang aturan skop, karena beberapa prosedur dan variabel dalam sebuah module dapat diakses dari bagian lain sebuah projek. Secara umum, module berdiri sendiri, yang berarti bahwa prosedur dalam module tidak perlu mengakses variabel dan prosedur yang ada di luar module, kecuali ketika dilewatkan sebagai argumen.

Kode 5.15 menyajikan modDadu, yang mengelompokkan beberapa prosedur yang terkait dengan dadu menjadi satu module untuk digunakan kembali pada program lain. Fungsi LemparDadu (baris 11-13) mensimulasikan suatu pelemparan dadu dan menghasilkan nilai balik. Fungsi LemparDanJumlahkan (baris 17-28) menggunakan sebuah struktur For (baris 22-24) untuk memanggil LemparDadu beberapa kali (yang diindikasikan oleh jumlahDadu). Fungsi GetCitraDadu (baris 30-37) menghasilkan nilai balik berupa sebuah Image dadu yang berkaitan dengan paraemeter nilaiDadu. Parameter Optional, namaCitraBasis, merepresentasikan prefiks dari nama citra yang akan digunakan. Jika argumen diabaikan, prefiks default “dadu” yang digunakan. Perhatikan bahwa module baru dapat ditambahkan ke dalam sebuah projek dengan mengklik kanan nama projek dan memilih Add > Module.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
' Kode. 5.15: modDadu.vb
' Kumpulan prosedur berkaitan dengan dadu.

Imports System.IO

Module modDadu

    Dim objekAcak As Random = New Random()

    ' melempar sebuah dadu
    Function LemparDadu() As Integer
        Return objekAcak.Next(1, 7)
    End Function ' LemparDadu

    ' prosedur menjumlahkan dadu
    Function LemparDanJumlahkan(ByVal jumlahDadu As Integer) _
        As Integer

        Dim i As Integer
        Dim jum As Integer = 0

        For i = 1 To jumlahDadu
            jum += LemparDadu()
        Next

        Return jum
    End Function ' LemparDanJumlahkan

    ' menghasilkan citra dadu
    Function GetCitraCadu(ByVal nilaiDadu As Integer, _
        Optional ByVal namaCitraBasis As String = "dadu") _
        As System.Drawing.Image

        Return Image.FromFile( _
            Directory.GetCurrentDirectory & _
            "\Citra\" & namaCitraBasis & nilaiDadu & ".png")
    End Function ' GetCitraCadu

End Module ' modDadu

FrmUjiModuleDadu pada kode 5.16 mendemonstrasikan penggunaan prosedur modDadu untuk merespon pengklikan tombol. Prosedur cmdLemparDadu1_Click (baris 23-27) melempar sebuah dadu dan mendapatkan citra default. Anda memanggil prosedur yang dimuat di dalam modDadu dengan menempatkan nama module dengan operator dot dan nama prosedur.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
' Kode 5.16: UjiModuleDadu.vb
' Mendomonstrasikan prosedur-prosedur di dalam modDadu

Imports System.Drawing

Public Class FrmUjiModuleDadu
    Inherits System.Windows.Forms.Form

    Friend WithEvents lblJum As Label ' menampilkan jumlah 10-pelemparan

    Friend WithEvents grupDadu As GroupBox

    ‘ Citra-citra dadu
    Friend WithEvents gbrDadu1 As PictureBox
    Friend WithEvents gbrDadu2 As PictureBox

    Friend WithEvents cmdLemparDadu1 As Button ' melempar dadu biru
    Friend WithEvents cmdLemparSepuluh As Button ' mensimulasikan 10 pelemparan
    Friend WithEvents cmdLemparDadu2 As Button ' melempar dadu merah

    ' Kode yang dibangkitkan oleh Visual Studio .NET

    Private Sub cmdLemparDadu1_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles cmdLemparDadu1.Click

        gbrDadu1.Image = modDadu.GetCitraCadu(modDadu.LemparDadu())
    End Sub ' cmdLemparDadu1_Click

    Private Sub cmdLemparDadu2_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles cmdLemparDadu2.Click

        gbrDadu2.Image = modDadu.GetCitraCadu(modDadu.LemparDadu(), _
            "daduMerah")
    End Sub  ' cmdLemparDadu2_Click

    Private Sub cmdLemparSepuluh_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles cmdLemparSepuluh.Click

        lblJum.Text = Convert.ToString(modDadu.LemparDanJumlahkan(10))
    End Sub  ' cmdLemparSepuluh_Click

End Class  ' FrmUjiModuleDadu




Gambar 5.20 Keluaran program pada kode 5.16

Latihan
1.       Carilah error pada tiap segmen program berikut dan jelaskan bagaimana error tersebut dapat diperbaiki:

a)        Sub Umum1()
        Console.WriteLine("Di dalam prosedur Umum1")

        Sub Umum2()
            Console.WriteLine("Di dalam prosedur Umum2")
        End Sub ' Umum2

    End Sub ' Umum1

b)       Function Jum(ByVal x As Integer, ByVal y As Integer) _
    As Integer

    Dim hasil As Integer

    hasil = x + y

End Function ' Jum

2.       Berapakah nilai x setelah tiap statemen ini dieksekusi?

a) x = Math.Abs(7.5)
b) x = Math.Floor(7.5)
c) x = Math.Abs(0.0)
d) x = Math.Ceiling(0.0)
e) x = Math.Abs(-6.4)
f) x = Math.Ceiling(-6.4)
g) x = Math.Ceiling(-Math.Abs(-8 + Math.Floor(-5.5)))

3.       Tulislah sebuah metode PangkatInteger(basis, eksponen) yang menghasilkan nilai balik

 


Asumsikan bahwa eksponen adalah sebuah integer positif dan basis adalah sebuah integer. Metode PangkatInteger harus menggunakan loop For/Next atau loop While untuk mengendalikan kalkulasi. Program harus membaca dua integer tersebut dari TextBox untuk basis dan eksponen.


1 comment:

  1. Logika Pemrograman: Bab 5. Visual Basic .Net Belajar Dari Contoh >>>>> Download Now

    >>>>> Download Full

    Logika Pemrograman: Bab 5. Visual Basic .Net Belajar Dari Contoh >>>>> Download LINK

    >>>>> Download Now

    Logika Pemrograman: Bab 5. Visual Basic .Net Belajar Dari Contoh >>>>> Download Full

    >>>>> Download LINK

    ReplyDelete