Sosyal Eklentiler

Kimler Sitede

Åžu anda 11 ziyaretçi Ã§evrimiçi

Bağış

Bu siteyi beğendiyseniz bağış yapabilirsiniz.


Sudoku Oyunu Yapmak
Makale - Visual Basic
Yazar ugokhan   
PerÅŸembe, 28 Åžubat 2008 11:30

Bu anlatımda bir SuDoku oyununun VB üzerinde nasıl yapılabileceğini anlatacağım. Projenin tamamını anlatmak biraz zorlayıcı olacağı için programın en can alıcı yerleri olduğunu düşündüğüm kısımlardan bahsedeceğim. Zaten 6.0 versiyonlu full proje haline buradan ulaşıp inceleyebilirsiniz. (şifresi: gokhanca.com)

SUDOKU NEDİR

SuDoku 9x9 bir düzlem üzerinde oynanan bir oyun. 2 Adet önemli kuralı var.

1) 3x3 lük kareler içerisinde 1'den 9'a kadar olan rakamları sadece 1 kere kullanabilirsiniz.

2) Herhangi bir yatay veya düşe sıra üzerinde 1'den 9'a kadar olan rakamları sadece 1 kez kullanabilirsiniz.

 

YARDIMCI BİLGİLER

Bu konu anlatımında bahsi geçen bazı nesneleri ve algoritmik mantığı daha iyi kavramak için aşağıda belirttiğim konu anlatımlarını okumalısınız. Büyük faydası olacaktır.

(bkz: yılan oyunu yapımı )
(bkz: picturebox paintpicture özelliği )
(bkz: pictureclip nesnesinin kullanımı )

 

 

DEĞİŞKEN YAPISINI TANIMLAMAK

SuDoku oyunu bilindiği gibi 9x9 luk bir matris üzerinde oynanır. Bu matris üzerindeki değerleri saklayabilmek için iki boyutlu bir dizi tanımlayalım. Bu diziyi aşağıdaki gibi tanımlayabiliriz.

  1. 'İki Boyutlu Bir Dizi Tanımlanıyor'
  2. Dim Tablo (1 to 9 , 1 to 9) As Integer

Bu diziyi kullanarak ilgili koordinattaki sayıyı saklayabiliriz. Tablonun sol-üst karesi 1,1 karesidir. Buna göre sağ-alt kare de 9,9 karesi olacaktır. Tablo üzerinde rakamları bu şekilde sakladık fakat oyun sırasında bazı kareler değişime kapalı olacak. Mesela oyun başında verilen ipucu karelerine tıklandığında bir işlem yapılmayacak. Çünkü bu rakamlar değişmez. Fakat boş karelere tıklandığında veya kullanıcının giriş yaptığı karelere tıklandığında bu karelerin değişebilir özellikte olması gerekir. Bu durumda her bir koordinat için bir de aktif-pasif kontrolü yapmamız gerekir. İşte bu durumda Tablo adlı diziyi Integer olarak değil, kendi istediğimiz değişken formatında tanımlayalım.

  1. 'Type Yapısı Tanımlanıyor'
  2. Type Ozellik
  3. Aktif As Boolean
  4. Deger as Integer
  5. End Type
  6.  
  7. 'Bu Ozelliklere sahip bir dizi tanımlanıyor'
  8. Public Tablo (1 to 9, 1 to 9) As Ozellik

Burada öncelikle Tablo dizisi için kullanacağımız bir özelliği TYPE komutu ile tanımladık. Daha sonra Ozellik adını verdiğimiz bu özellikleri Tablo dizisinin tipi için kullandık. Dikkat edilirse Dim yerine Public ifadesini kullandım. Eğer projeye bir modül eklerseniz ve yukarıdaki tanımlamaları modül içerisine eklerseniz Tablo adlı diziyi proje kapsamındaki tüm modül ve formlarda kullanabilirsiniz. Yani tek tanımlama ile her yerde kullanılabilen bir dizi değişkeni olur. Eğer Form'un General - Decleration bölümünde tanımlasaydık diğer formlar bu diziyi tanımayacaktı

Şimdi tekrar Tablo özelliklerine dönelim ve bunun nasıl kullanıldığı hakkında minik bir uygulama yapalım. Aşağıda 3x3'lük minik bir SuDoku hazırladım. Oyunun başında 3 tane rakam bize ipucu olarak verilmiş (4 - 2 ve 8). Bu kareler oyun boyunca değiştirilemez. Diğer kareler ise oyun sırasında her an değiştirilebilir.

gokhanca

Oyun başında bütün kareler değiştirilebilir kare olarak ayarlanır. Ayrıca tüm karelerin değeri sıfır yapılır.

  1. 'Başlangıç Ayarları Yapılır'
  2. For i=1 to 3
  3. For j=1 to 3
  4. Tablo( i , j ).Aktif = True
  5. Tablo( i , j ).Deger = 0

İpucu kareleri ise oyun başında yazılır ve değiştirilemez kare olarak ayarlanır.

  1. Tablo (1,1).Deger = 4
  2. Tablo (1,1).Aktif = False
  3.  
  4. Tablo (2,3).Deger = 2
  5. Tablo (2,3).Aktif = False
  6.  
  7. Tablo (3,2).Deger = 8
  8. Tablo (3,2).Aktif = False

Bu sayede hem ilgili koordinattaki rakam değerini tutmaktayız hem de seçilen kare üzerinde işlem yapma iznini takip edebilmekteyiz. Seçilen karenin Aktif özelliği False ise demek ki bu kare üzerinde bir işlem yapılmayacaktır.

 

 

MOUSE İLE SEÇİM YAPMAK

İnternette gördüğüm birçok SuDoku oyununda kullanıcıya klavyeden giriş izni verilmiş. Böyle oyunlarda klavye kullanmak oyuncuyu bıktırır. Üstelik her seferinde kullanıcı klavyede hangi tuşa bastı kontrolü yapmak çok can sıkıcıdır. Herşeyin mouse ile halledildiği bir oyun daha oynanabilir ve güzel olacaktır.

Bu yüzden ben oyunu tamamen mouse kontrollü olarak tasarladım. Yapmanız gereken PictureBox üzerinde Mouse_Up() olayını kullanmak. Bu kontrol ile PictureBox nesnesi üzerinde hangi kareye tıkladığınızı bulabilir ve o kareye uygun rakam resmini koyabilirsiniz. Şimdi bunu adım adım yapalım.

Öncelikle oyun içerisinde kullanacağımız rakam resimlerini Paint programında hazırlayalım. Her bir karesi 33x33 pixel olacak şekilde rakam kutucuklarının resmini çizin. Çizdiğimiz rakam resimleri aşağıdaki gibi olabilir. Ben programımda bu resmi kullandım. Bu resim tek parça bir resim olup PicClip nesnesi ile resim bir matris şeklinde algılanıp istenilen parçası kullanılabilir. Sanki 10 x 4 lük bir matrismiş gibi düşünün. Sol üst köşe 0 numaralı indis olmak üzere sağa doğru indis değeri artarak devam eder. Sonra bir alt satıra geçer. Bu şekilde en son pembe renkli 9 karesinin değeri 39 olur.

Resim üzerindeki istenilen kareye ulaşmak için [kare değeri] + [işlem tipi] formülü kullanılabilir.

Mesela,

İçinde 4 yazan bir kareyi seçmek için [4] + [20] = 24 nolu resim alınır. 4 nolu karenin rengi turuncu olmuş olur. Buradaki 20 değeri resimde 3. sıraya inmek içindir. Buradaki resim yerleşimleri tamamen size kalmış bir şey.

(bkz: pictureclip nesnesinin kullanımı )

gokhanca

Buradaki herbir kare 33x33 ebatında olduğuna göre toplam oyun ekranının boyu 9x33 = 297 pixel olmalıdır. Yani 297x297 ebatında bir PictureBox oluşturalım. Bunun için hem Form'un hemde PictureBox'ın ScaleMod değerini Pixel olarak ayarlayın. Daha sonra yine PictureBox'a ait olan Height, Width, ScaleHeight, ScaleWidth değerlerini 297 olarak ayarlayın. Sıra geldi PictureBox nesnesini 9x9 luk dilimlere ayırmaya. Bundan sonraki işlemlerde PictureBox kelimesi yerine o nesneye verdiğim Ekran adını kullanacağım. Yani PictureBox'ınızın Name özelliğine Ekran yazın.

Ekranı bölümlere ayırmak için Scale özelliği kullanılır. Önce sol-üst köşe sonra da sağ-alt köşenin değerleri girilerek Ekran bölümlendirilir. Bunu Form_Load olayına yazabilirsiniz

  1. Ekran.Scale (1,1)-(10,10)

Artık Ekran nesnesi, herbiri 33x33 ebatında olan 9x9'luk karelere bölündü. Şimdi istediğimiz bir koordinatına istediğimiz bir rakam resmini yapıştırabiliriz. Bunu aşağıdaki kod ile yaparız. Ekran üzerindeki a,b koordinatına istenilen rakam resmi konulur.

  1. Ekran.PaintPicture Resim_Kaynağı, a, b

Bu işlemi PicClip nesnesi ile nasıl yapıyoruz. Gelelim bu a,b koordinat değerleri mouse ile nasıl bulunur? Bunun için Ekran nesnesi üzerinde MouseUp olayını kullanırız.

  1. Private Sub Ekran_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
  2. A=Fix(X)
  3. B=Fix(Y)
  4. 'Oyun başında verilen kareler seçilemez. Bu kareler Aktif değildir'
  5. If Tablo(A,B).Aktif = True Then
  6. Ekran.PaintPicture rakam.GraphicCell(Tablo(A,B).Deger + 20) , A , B
  7. End If
  8. End Sub

Yukarıdaki bu kodu aşağıdaki resme göre açıklayalım. Diyelim ki 5,3 karesine tıklanıldı (turuncu kare). Bu kareye tıklanıldığında A = 5 ve B = 3 olur. Sonra Tablo (5,3).Aktif Değerinin True olup-olmadığı kontrol edilir. Eğer True ise bu kareye değer girişi yapılabilir. Karenin seçildiğini belli etmek için turuncu renkli kare efekti kullanılır. Bu da kare içindeki değerin 20 fazlasına karşılık gelen rakam resmidir. Rakam resim indeksi için yukarıdaki rakamlar resmine bakabilirsiniz. Bu resim değeri alınıp 5,3 koordinatına konur.

gokhanca

 

SEÇİLEN KAREYE RAKAM GİRİŞİ

Ekran_MouseUp olayını kullanarak ekrandaki bir kareyi işaretlemiş olduk. Şimdi sıra seçilen kareye rakam girmeye geldi. Seçilenen son karenin koordinatlarını A ve B değişkenleri tutmakta. Her rakam için bir buton oluşturalım ve bu butonlara bastığımızda gidip A,B koordinatlı kareye ilgili resmi koysun. Bütün butonların Index ve Caption değerlerini sırasıyla 1'den 9'a kadar oluşturalım. Böylece 9 adet buton nesnesini bir dizi gibi kullanabiliriz.

  1. Private Sub Command1_Click (Index As Integer)
  2. Ekran.PaintPicture rakam.GraphicCell(Index + 10) , A , B
  3. Tablo(A,B).Deger=Index
  4. End Sub

Diyelim ki 4 nolu butona bastık. Index değeri 4 olduğu için 4 + 10 = 14 nolu resmi ekranın A,B koordinatına koyacaktır. Aynı zamanda veri girişi yapıldığı için Tablo dizisinin A,B koordinatının değeri girilen Index değerine eşitlenir.

 

SUDOKU KURALLARININ UYGULANMASI

Sudokudaki ilk kural 3x3'lük hücre içerisinde aynı rakam bulunamaz. Öncelikle seçtiğimiz rastgele bir (X,Y) koordinatlı karenin hangi 3x3'lük karede olduğunu öğrenmeliyiz. Sonra da o kare içerisindeki kareleri tarayarak kontrol işlemini yapmalıyız.

Diyelim ki (5,3) karesini seçtik (Yukarıdaki resimde turuncu renkle belirtilen 7 değerindeki kare). Bu karenin bulunduğu 3x3'lük kareyi nasıl buluruz? Öncelikle sadece 3x3'lük kareleri düşünelim. Sadece 3x3'lük kareleri gördüğümüzde, aradığımız 3x3'lük kare (2,1) karesidir. Bu durumda 5 ve 3 koordinatlarını kullanarak bu değerleri bulmalıyız. Dikkat edilirse 3'ün katları şeklinde bir ilerleme var. Fakat hemen bölemeyiz. Küçük bir matematiksel hile kullanarak her koordinatı 2 ile toplayıp 3'e böleriz. Çıkan sonucun tam kısmı bize istediğimiz sonucu verir.

  1. kx = Fix((X+2)/3)
  2. ky = Fix((Y+2)/3)
  3.  
  4. kx = Fix((5+2)/3)=2
  5. ky = Fix((3+2)/3)=1

Artık aradığımız 3x3'lük kareyi bulduk. Şimdi bu kare içerisinde tarama yaparak 7'ye eşit başka kare var mı kontrol edilir.

  1. For tx = 2 To 0 Step -1
  2. For ty = 2 To 0 Step -1
  3. 'Bu hücre içerisinde 7 ye eşit bir değer var mı kontrol edilir'
  4. If Tablo(kx * 3 - tx, ky * 3 - ty).deger = 7 Then
  5. 'İşlem İptal Edilir'
  6. End If

Bu işlemi bir Function olarak tanımlayalım. Function üzerine X,Y koordinatlarını ve oraya yerleştirmeyi düşündüğümüz Sayı değişkeninin değerini göndereceğiz. Cevap olarak da bize TRUE / FALSE diyerek durumun müsait olup-olmadığını geri döndürecek.

  1. Function HucreKontrol (X as Integer , Y as Integer , Sayi as Integer) as Boolean
  2. 'Işlemin Doğru olacağı varsayılarak başlanır.'
  3. HucreKontrol = True
  4. kx = Fix((X+2)/3)
  5. ky = Fix((Y+2)/3)
  6. For tx = 2 To 0 Step -1
  7. For ty = 2 To 0 Step -1
  8. ' Bu hücre içerisinde Sayi degiskenine eşit bir değer varsa işlem iptal edilir'
  9. If Tablo(kx * 3 - tx, ky * 3 - ty).deger = Sayi Then
  10. ' İşlem İptal Edilir.'
  11. HucreKontrol = False
  12. Exit Function
  13. End If
  14. End Function

Bu Function'u kullanarak herhangi bir kare için 3x3'lük kare kontrolü yaptırılabilir. Gelelim 2. kurala. Bu kurala göre aynı yatay veya düşey hizada aynı rakam olmamalı. 1'den 9'a kadar o sıradaki koordinatlar üzerinde tarama yapılarak bu kontrol yaptırılabilir. Herhangi bir X,Y karesi için kontrol :

  1. For i = 1 to 9
  2. ' Düşey Tarama Kontrolü'
  3. If Tablo(X,i).Deger = Tablo(X,Y).Deger And i <> Y Then
  4. 'İşlem iptal edilir.'
  5. End if
  6.  
  7. ' Yatay Tarama Kontrolü'
  8. If Tablo(i,Y).Deger = Tablo(X,Y).Deger And i <> X Then
  9. ' İşlem iptal edilir.'
  10. End if

Yukarıdaki tarama işlemini HucreKontrol Function'u içerisine yerleştirelim. Böylece X,Y,Sayi parametrelerini göndererek X,Y karesine Sayi değişkeninin yerleşmesinin uygun olup-olmadığını kontrol etmiş oluruz. Tek fonksiyon ile bir kareye atanacak değerin uygunluğu test edilmiş olur.

Fonksiyonumuz bittiğinde kullanımı şu şekilde olur. Diyelim ki (4,5) karesine 9 değerini yerleştirmek istiyoruz. Bunu kontrol ettirelim.

  1. If HucreKontrol(4,5,9) = True Then
  2. ' Sonuç Olumlu. Yerleştirme Yapılır'
  3. Else
  4. ' Sonuç Olumsuz. Yerleştirme İptal Edilir'
  5. End If

SuDoku programının en temel hareketleri bu şekildedir. Amaç SuDoku kurallarına uygun sayı girişi yapmaktır. Ben, bu ders içerisinde yerleştirmenin nasıl olacağı ve kontrolünü anlatmaya çalıştım. Her türlü eleştiriniz için mesaj yazabilirsiniz.

 

Yorumlar  

 
0 #1 2010-11-02 22:18
gayet güzel anlatmısınız ben bilgisayar ögretmenliginde okuyorum visual basic dersınde bir proje secip anlatmamızı istedi hoca.Ben senın bu projeyı cok begendım bir sakıncası yoksa vize sınavında bu projeyi sunacam.Baskalarının projelerını anlatabilirsini z dedi hoca.projeyi tekrar inceledigimde anlamadıgım bi yer olursa bana yardımcı olabilir misiniz?
Alıntı
 

Yorum ekle

TCK'ya aykırı, yasadışı ve genel ahlaka aykırı yazılar ile konu dışında yazılar, istekler, spam ve reklam amaçlı mesajlar yazılması YASAKTIR. Bu tür yazılar görüldüğü anda tarafımdan silinecektir. Herhangi bir uygunsuzluğun olduğunu düşündüğünüz yazılar için lütfen bana eposta yoluyla haber veriniz.


Güvenlik kodu
Yenile