Visual Basic ile Sudoku Oyunu Yapımı

By | 28 Şubat 2008

Bu anlatımda bir Sudoku oyununun Visual Basic ü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.

SUDOKU NEDİR

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

  1. 3×3 ‘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: Visual Basic ile Yılan Oyunu Yapımı)
(bkz: picturebox paintpicture özelliği )
(bkz: pictureclip nesnesinin kullanımı )

DEĞİŞKEN YAPISINI TANIMLAYALIM

Sudoku oyunu bilindiği gibi 9×9 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.

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.

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ı.

18_sema02

Şimdi tekrar Tablo özelliklerine dönelim ve bunun nasıl kullanıldığı hakkında minik bir uygulama yapalım. Yanda 3×3’lük minik bir Sudoku hazırladım. Oyunun başında 2, 4 ve 8 rakamları bize ipucu olarak verilmiş olsun. Bu kareler oyun boyunca değiştirilemez özelliktedir. Diğer kareler ise oyun sırasında her an değiştirilebilir özelliktedir.

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

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

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 33×33 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×4 lük bir matris üzerindeymiş gibi düşünün. Sol üst köşe sıfır 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.

18_sema04

Buradaki herbir kare 33×33 ebatında olduğuna göre toplam oyun ekranının genişliği 9×33 = 297 pixel olmalıdır. Yani 297×297 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 9×9 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.

Artık Ekran nesnesi, herbiri 33×33 ebatında olan 9×9’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 yapabiliriz. Ekran üzerindeki a,b koordinatına istenilen rakam resmi konulur.

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

18_sema03

Yukarıdaki bu kodu yandaki 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 konulur.

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.

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 3×3’lük hücre içerisinde aynı rakam bulunamaz. Öncelikle seçtiğimiz rastgele bir (X,Y) koordinatlı karenin hangi 3×3’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 3×3’lük kareyi nasıl buluruz? Öncelikle sadece 3×3’lük kareleri düşünelim. Sadece 3×3’lük kareleri gördüğümüzde, aradığımız 3×3’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.

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

 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.

Bu Function’u kullanarak herhangi bir kare için 3×3’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 :

 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.

Sudoku programının en temel hareketleri bu şekilde yapabiliriz. Bu anlatımdaki amacım Sudoku kurallarına uygun sayı girişi yapmaktı. 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.

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir