Forum: Ders Arası RSS
Türler ile ilgili basit bir alıştırma örneği
Bir yapı türü, bir enum türü, temel türler ve işlevler üzerine alıştırma
Avatar
mert #1
Üye Ara 2010 tarihinden beri · 194 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Türler ile ilgili basit bir alıştırma örneği
Yapılar üzerinde alıştırmalar yapıyorum. Derslerde sunulan örneklerden bağımsız olarak ileride sınıflar ile de kullanabileceğim bir model geliştireyim istedim.

Bu alıştırmada hem temel türleri, hem işlevleri hem de yapı, enum gibi türleri kullanmaya çalıştım. İlerledikçe ve alıştıkça örneğimi de geliştirebileceğimi düşünüyorum.

import std.stdio;
 
enum DarbeTipi {Bıçak = 10, Kılıç = 20, Tabanca = 50, Tüfek = 70, Bomba = 100 }
 
struct Kahraman
{
    double güç;
    double para;
}
 
double değerlendir(in double parametre, in double değer)
{
    double ölçek;
    ölçek = parametre - (parametre * değer);
    
    return ölçek;
}  
 
Kahraman darbeAl(in Kahraman karakter, in double darbe)      // daha kısa yollar dene
{
    Kahraman darbeli;
    if (darbe == 10) {
        darbeli.güç  = değerlendir(karakter.güç, 0.1);       // Başka bir işlev ile
        darbeli.para = değerlendir(karakter.para, 0.1);
    } else if (darbe == 20) {
        darbeli.güç  = değerlendir(karakter.güç, 0.2);
        darbeli.para = değerlendir(karakter.para, 0.2);
    } else if (darbe == 50) {
        darbeli.güç  = karakter.güç - (karakter.güç  * 0.5); // Başka bir işlevsiz
        darbeli.para = karakter.para - (karakter.para * 0.2);
    } else if (darbe == 70) {
        darbeli.güç  = karakter.güç - (karakter.güç  * 0.7);
        darbeli.para = karakter.para - (karakter.para * 0.2);
    } else if (darbe == 100) {
        darbeli.güç  = değerlendir(karakter.güç, 0.9);
        darbeli.para = değerlendir(karakter.para, 0.3);
    } else {
        darbeli.güç  = 0;
        darbeli.para = 0;
    }
    return darbeli;
}    
 
void main()
{
    Kahraman başlangıç = Kahraman(100, 10_000);
    
    writefln("Herhangi bir kahraman için başlangıç  %s - %s ", 
                başlangıç.güç, başlangıç. para);
    writeln();
    Kahraman benimKahramanım = başlangıç;
    writefln("Yeni bir kahraman için başlangıç %s - %s",
                benimKahramanım.güç, benimKahramanım.para);
    
    writeln("Kahramanın bir tür darbe aldı");
    
    enum darbe = DarbeTipi.Bomba// Bıçak, Kılıç, Tabanca, Tüfek, Bomba
    
    auto kahramanDurumu = darbeAl(benimKahramanım, darbe);
    
    writefln("Kahramanın durumu:  ♥ %s - € %s",
                kahramanDurumu.güç, kahramanDurumu.para);
}

Örneğimde darbe tipini değiştirerek kahramanı çeşitli biçimlerde güçsüz ve parasız bırakabiliyorum. Yine ek bir yapı tanımlayarak yeni güçler ve kazanç kaynakları veya donatımsal araç gereçler eklemek mumkun. Öğrenme sürecindeki arkadaşlarımla paylaşmak istedim.

mert
mert
Bu mesaj 3 defa değişti; son değiştiren: mert; zaman: 2011-04-09, 17:35.
acehreli (Moderatör) #2
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Ne güzel programlar gelmeye başladı! :)

Hemen gözüme çarpan bir iki nokta oldu.

1) Mümkünse değişkenin ilk değerinin tanımlandığı yerde verilmesi önerilir:

    double ölçek = parametre - (parametre * değer);

Her zaman öyle olması gerekmez ama burada olabilir gibi görünüyor.

2) Bence darbeAl'ın içinde bir if zinciri değil, 'final switch' kullanılması daha uygun olur. DarbeTipi diye okunaklı değerleri olan okunaklı bir tür varken 10, 20 gibi değerler anlaşılamıyor:

    final switch (darbe) {
    case DarbeTipi.Bıçak:
        darbeli.güç  = değerlendir(karakter.güç, 0.1);       // Başka bir işlev ile
        darbeli.para = değerlendir(karakter.para, 0.1);
 
        break;
// ... 

Tabii onu yapmak için işlevin parametresinin türü de DarbeTipi olmalı.

3) Bir de şu satır üzerinde düşüncelerim var:

    auto kahramanDurumu = darbeAl(benimKahramanım, darbe);

darbeAl, bir Kahraman alıyor ve onun darbe almışı olan yeni bir Kahraman döndürüyor. Fonksiyonel programcılık açısından çok güzel ve belki de en doğrusu o. Ancak, nesne yönelimli bakış açısına alışmış birisi olarak ben burada yan etki olmasının daha uygun olabileceğini düşündüm. Eğer darbeAl()'ı bir üye işlev yaparsak, var olan karakterin kendisi değişir. (Bu konu 'Üye İşlevler' bölümü ile ilgili):

struct Kahraman
{
    double güç;
    double para;
 
    void darbeAl(in DarbeTipi darbe)
    {
        // ... burada 'güç' ve 'para' üyeleri değiştirilir ...
    }
}

Ali
Avatar
mert #3
Üye Ara 2010 tarihinden beri · 194 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
1) Mümkünse değişkenin ilk değerinin tanımlandığı yerde verilmesi önerilir:

Tamamen haklısınız. Daha fazla dikkat gerekiyor.

2) Bence darbeAl'ın içinde bir if zinciri değil, 'final switch' kullanılması daha uygun olur. DarbeTipi diye okunaklı değerleri olan okunaklı bir tür varken 10, 20 gibi değerler anlaşılamıyor:
final switchbir sonraki alıştırma olarak aklımdaydı. Örneği birçok açıdan tekrar tekrar yazacağım. Hem ayrıca "sihirli sabitlerden kaçınınız" demiştiniz, hatırladım.


3)Bir de şu satır üzerinde düşüncelerim var:

    auto kahramanDurumu = darbeAl(benimKahramanım, darbe);


darbeAl, bir Kahraman alıyor ve onun darbe almışı olan yeni bir Kahraman döndürüyor. Fonksiyonel programcılık açısından çok güzel ve belki de en doğrusu o. Ancak, nesne yönelimli bakış açısına alışmış birisi olarak ben burada yan etki olmasının daha uygun olabileceğini düşündüm. Eğer darbeAl()'ı bir üye işlev yaparsak, var olan karakterin kendisi değişir. (Bu konu 'Üye İşlevler' bölümü ile ilgili):

Yapılar bölümüne geldiğimde o tür olanaklarla ilk kez karşılaşmış olduğumdan sınıflara kadar bir ön okuma yapıp yeniden geriye dönmeyi seçmiştim. Temel türler ve tür tanımlama bölümlerini tüm kitap boyunca yeniden gözden geçirerek özet bir hızlı başvuru kaynağı hazırladım kendime. Aynı özet çalışmasını işlevler için de hazırladım, üye işlevlere kadar. konuları iyice öğrenip içselleştirmeyi başardıkça - ki bu içselleştirme yeteri kadar alıştırma çözmeden pek oluşmuyor- belli başlı konularda hızlı başvuru kaynağım da olmuş olacak böylelikle. Bu sayede eksiklerimi doğru biçimde tamamlayabileceğimi düşünüyorum. 

Benim gibi betik dillerinden derlemeli bir dile geçen öğrencilerin D içerisindeki bilgiler, olanaklar kurallar veya disiplinlerle aşina olması değil, öğrenmeye başlaması bu tür çabaları gerekli hale getiriyor. Çünkü kaynaklar yeterli ve bol. (örneğin forum, örneğin d.ershane, örneğin özenli bir öğretmen) kolay bulunmuyor hepsi bir arada.

Örneğin php'de nesne yönelimi olmakla beraber yapılar gibi olanaklarla karşılaşamıyorsunuz. Hem ayrıca php öğrenirken önümüze bu kadar ayrıntılı bir öğrenme mekanizmasını da kimse alıp koymamıştı işin doğrusu. Kaynağı bol, bilgi yönünden verimliliği kıt olan öğrenme mekanizmalarının, öğretme yerine aşina etme gibi bir işlevi olduğunun farkına varıyorum. Şimdi D öğrenirken, doğru kaynaklardan doğru yöntemlerle öğrenmenin keyfini çıkarmaya çalıştığımı itiraf etmeliyim :-)

Örnek alıştırmamı belirttiğiniz noktalara dikkat ederek geliştireceğim.Teşekkür ederim hocam.

mert
mert
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Öğrenmenin nasıl olması gerektiğini görüyoruz! ;)

Umarım benim tekrarlarımdan rahatsız olmuyorsunuzdur. Ben C++ forumlarını izlerken hiç bilmediğim konularda hiç anlamadığım öneriler okurdum. Örneğin birisi bir şey sorardı; yanıtlar arasında "bir de şu çözüm var" diye bir öneri geçerdi. Tabii ben baştan hiç bir şey anlamazdım; kafamda küçücük bir iz kalırdı. Ama o tekrarlar eninde sonunda bende de bilgi haline geldiler.

Örneğin "sihirli sabitlerden kaçınınız" gibi bir söz, herhalde her okuyanda farklı bir iz bırakmıştır. Ama aynı konuyu böyle bir program üzerinde görüp konuşunca herhalde unutulmaz.

Programlara devam! :)

Ali
erdem (Moderatör) #5
Üye Tem 2009 tarihinden beri · 978 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
Örneğin "sihirli sabitlerden kaçınınız" gibi bir söz, herhalde her okuyanda farklı bir iz bırakmıştır.

Evet. Bunu 7 sene önce sizden duyduğumda bir değişken nasıl sihirli olur diye düşünmüştüm.

Demek ki değişkenin de sihirlisi oluyormuş :-p

Ben kendi adıma konuşmak gerekirse, o tekrarlardan aklımda kalanlar C++ konusunda öğrendiklerimin temelini oluşturuyor. Unuttuklarımı da zaten defalarca soruyorum :)
Avatar
mert #6
Üye Ara 2010 tarihinden beri · 194 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: örneğin üye işlev ile düzenlenmiş hali
Örneğimi belirttiğiniz noktalara dikkat ederek yeniden toparladım. Böylelikle hem daha kısa kod yazmış oldum, hem daha iyi anlaşılır oldu benim için işlevler ve türler. Üye işlevler çok şık.

import std.stdio;
import std.string;
 
enum DarbeTipi { Bıçak, Kılıç, Tabanca, Tüfek, Bomba }
 
struct Kahraman
{
    double güç;
    double para;
    
    const string toString()
    {
        return format("♥ %02s € %02s", güç, para);
    }
    
    void darbeAl(in DarbeTipi darbe)
    {
            final switch(darbe) {
            
            case DarbeTipi.Bıçak:
            güç  = değerlendir(güç,  0.1);
            para = değerlendir(para, 0.1);
            break;
            
            case DarbeTipi.Kılıç:
            güç  = değerlendir(güç,  0.2);
            para = değerlendir(para, 0.2);
            break;
            
            case DarbeTipi.Tabanca:
            güç  = değerlendir(güç,  0.5);
            para = değerlendir(para, 0.3);
            break;
            
            case DarbeTipi.Tüfek:
            güç  = değerlendir(güç,  0.7);
            para = değerlendir(para, 0.4);
            break;
            
            case DarbeTipi.Bomba:
            güç  = değerlendir(güç,  0.9);
            para = değerlendir(para, 0.5);
            break;
            
           }
 
       }
}
 
double değerlendir(in double parametre, in double değer)
{
    double ölçek = parametre - (parametre * değer);
    
    return ölçek;
}
 
void main()
{
    auto başlangıçKahramanı = Kahraman(100, 10_000);
    
    auto benimKahramanım    = başlangıçKahramanı;
    
    enum darbe = DarbeTipi.Tüfek;
    
    benimKahramanım.darbeAl(darbe); // benim kahramanım artık tüfek darbeli
    
    writefln("%s - %s", başlangıçKahramanı, benimKahramanım);
}

İlerledikçe hem örneği geliştirip hem kod satırlarını mümkün olduğu kadar kısaltmayı düşünüyorum.
Teşekkürlerimle.

mert
mert
Bu mesaj mert tarafından değiştirildi; zaman: 2011-04-16, 03:10.
acehreli (Moderatör) #7
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Çok güzel. :) Tabii bu işin sonu yok...

Mutlaka bir şey söylemek gerekirse, gözüme ilk çarpan, değerlendir işlevi oluyor. Kendi ismi ve parametre isimleri anlaşılmasına yardımcı olmuyor. Ancak işlevin içine baktıktan sonra değer'in "yüzde şu kadar azalt" demek olduğunu anlayabildim.

Tabii her zaman azaltma anlamına gelmeyeceğini de biliyorum. O yüzden değerlendir gibi genel bir isim kullanmak zorunda kalınıyor.

Bundan sonraki adım, DarbeTipi'ni enum yapmak yerine Darbe diye bir sınıf sıradüzeni kurmak olabilir. Nesne yönelimli programlamaya tam sadık olanlar için switch deyimi bir işarettir: o deyimin görüldüğü yere bir sıradüzen gelebilir. :)

Darbenin etkisi, sınıfları olmayan C'de switch ile yazılmak zorundadır. (Aslında işlev göstergeleriyle C'de de nesne yönelimli programlama yapılır ama çetrefillidir.) D gibi dillerde ise aşağıdaki gibi de olabilir. (Not: enum ve switch yasak değildir. :) Bir işaret olarak görülebileceğini söylemek istiyorum.) (Ayrıca kodu derlemedim bile; hatalıdır.)

interface Darbe
{
    double güçDeğerlendir(in double güç);
    double paraDeğerlendir(in double para);
}
 
class BıçakDarbesi : Darbe
{
    double güçDeğerlendir(in double güç)
    {
        return güç - (güç * 0.1);
    }
 
    double paraDeğerlendir(in double para)
    {
        return para - (para * 0.1);
    }
}
 
// ... diğer darbeler de benzer şekilde ... 

Şimdi darbeAl çok daha kısa olur. Hatta yüzde değerleri bütünüyle darbelerle ilgili sınıflar içinde bulunurlar:

struct Kahraman
{
// ...
    void darbeAl(in Darbe darbe)
    {
        güç = darbe.güçDeğerlendir(güç);
        para = darbe.paraDeğerlendir(para);
    }
}

Sonra çağrıldığı yerde:

    auto darbe = new TüfekDarbesi;
 
    benimKahramanım.darbeAl(darbe);

Bu yöntem, darbelerin davranışlarındaki farklılıkların sayısı fazla olduğunda daha da yararlı olacaktır.

Ama fikir olarak gösteriyorum. Kendim de enum ve switch ile yapardım herhalde. :)

Ali
Avatar
mert #8
Üye Ara 2010 tarihinden beri · 194 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Tasarım üzerine
Yönlendirmeniz yeni yeni yollar açıyor önümde. Ama daha sınıflara girmiş bile değilim. O aşamalara geldiğimde ise sanırım bir hava - yer savaş oyununun basit örneklerine adımlar atabilirim. (barışçıl biriyim oysa, sırf alıştırma için:-)
Örneğin hızı, tipi kapasiteleri belirgin bir uçak sınıfımız olur. Bu bir yerden havaya füze sistemi ile karşı karşıya gelebilir. Farklı uçaklar farklı kapasite ve menzillerde farklı mac hızlarında ve dönüş kabiliyetleri belli g değerleri üzerinde olan füzelerle karşılaştırılabilinir.

Dediğiniz gibi sonu yok hiç. Burada önemli olan tasarım sanıyorum. İnterface olanakları müthiş bir yetenek. Bir cgi bağı ile internet üzerinde bile bir çok kullanıcının ortaklaşa rahatlıkla oynayabileceği bir simülasyon oluşturmak çok zor olmasa gerek.

Demek ki daha çok alıştırma yaparak daha iyi kavramam gerekiyor D'ili.

Yönlendirmeniz nerelere aldı götürdü örneği görüyor musunuz? :-)

mert
mert
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Forum: Ders Arası RSS
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-18, 03:59:07 (UTC -08:00)