Forum: Ders Arası RSS
Basitten karmaşığa bir kodun hikayesi
Örneklemeler
Sayfa:  önceki  1  2  3  sonraki 
Avatar
Salih Dinçer #16
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj ID 8052
mert:
in anahtar kelimesi kullanmadan da işlevlerimize parametreler geçirebiliriz. Ancak bu şekilde davrandığımızda o parametrenin işlevimizin içinde değişmeyeceği gibi bir garantimiz olamıyor. Başka bir yaklaşım da; eğer sorunumuz sadece parametremizin işlev içinde değişmiyor olduğu garantisini sağlamaksa const, immutable gibi değişmezliği belirli seviyelerde bize sunan anahtar kelimeleri kullkanabiliriz. Benim şu aşamada kullandığım in parametresi hem bu örneği oluştururken belirlediğim düzeyin, birazda kodlama alışkanlığımın ve biraz da in anahtar kelimesinin arkasında iş gören farklı yordamların olabileceği önsezisinden kaynaklanmaktaydı ki senin de referans verdiğiniz konu başlığında http://ddili.org/forum/thread/970 Ali hocam  bu olanağa değinmiş.

acehreli:
Aslında tam aynı anlamda değiller çünkü 'in' ayrıca 'scope' belirtecini de içerir. (scope yukarıdaki bağlantıda geçiyor ama henüz hiçbir derleyici onu desteklemiyor.)

Sorunu tam olarak kavrayamayıp beklediğin yanıtı verememiş olabilirim. Ama detaylandırmak her zaman mümkün elbet. Bu doğrultuda katkıda bulunmak ister misin Salih hocam?

An itibariyle bu konuda kullanmaya başladığımız in belirteçleri hakkında ekleyebileceğim bir şey yok. Ancak şimdi assembly kodlarını inceleyerek bunun biz programcılar için sadece bir takı olduğumu yoksa bir araç ve gereç gibi bir işi yapan belirteç mi olduğundan emin olabilirim. Konuyu çok şişirmemek için hemen aşağıda iletimi düzenleyerek cevaplayacağım:

Şu örneği denedim:
int func(int foo, in int bar) {
  foo += bar;
  return foo;
}
Assembly kodlarına baktım ve vardığım sonuç şu:

Öncelikle in ile const arasında hiç bir fark yok! Birisi diğerinin alias'ı gibi çünkü MD5SUM ile de dosyanı birebir aynı olduğunu kontrol ettim. Ancak bu takıları kullanmadığımız zaman parametre değişkenlerine bellekte farklı bir şekilde yer ayrılıyor. Yine de main() ve func() işlevleri içindeki assembly komutlarında en ufak bir şey değişmediğini söyleyebilirim...:)

Değişen belki de tek şey var, yukarıdaki örnekte eğer in belirteçini ilk parametre önüne koyarsanız doğal olarak derleme hatası alıyorsunuz. Sanırım bütün bu olanaklar yazılım geliştikçe bir şeylerin karışmasını engellemek için türetilmiş. Çünkü siz örnekti  foo değişkenini const veya in özelliği verirseniz, bunun içeriğini değiştiremeyeceğiniz için işlevden çıkana kadar güvenle kullanabilirsiniz. Çünkü değişmeyeceğinin garantisi var, yoksa derlenirdi...

Özetle bunlar bir takıdan çok derleyici için bir belirteç, yoksa kenara bir yere "aman bu değişkeni içeride kullanma" diyebilirdik. Öyle ya, scope(exit) gibi olanaklar içinde bu değerin ilk halini kullandığımızda işler karışabilirdi. Şimdi her şeyi daha net anlıyorum...:D
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Bu mesaj Salih Dinçer tarafından değiştirildi; zaman: 2012-10-19, 12:23.
Avatar
mert #17
Üye Ara 2010 tarihinden beri · 194 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj ID 8053
acehreli:
Daha çok bir kişisel tercih ve belki de yazının bu aşamasında göstermek istemedin ama ben atamalı işleçleri yeğliyorum:

Atamalı işleçler benim de tercihim, ancak düz mantık kolay kavranır şu aşamada diye düşündüğümden
acehreli:
bıçakDarbeliKahraman değişkeninin ismini bıçakDarbeliEnerji diye değiştirmek daha uygun olacak gibi geliyor.
İleriki aşamalarda enerji - para gibi sorunlarımız ortaya çıkacak ve işte o zaman bu değişim bir zorunluluğa dönüşecek
acehreli:
'in' çok yararlı bir anahtar sözcük. (Ben bu gibi anahtar sözcüklere belirteç de diyorum.)
Salih:
Sanırım İngilizce'deki "keyword", do, while, for, if dahil her dil olanağının karşılığı oluyor. Bu bağlamda doğru ama bu takıları ayırma taraftarıyım. Belirteç de çok güzel görünüyor çünkü işaretlerden oluşanlarına da işleç diyoruz. Üstelik "abahtar sözcük" iki sözcükten oluştuğu için kullanımı zor görünüyor. Eğer Ali hocam kitapta sıklıkla belirteç kullandıysa bence böyle devam edelim.
Belirteç deyip dememek konusunda yazarken kararsız kalmıştım. Sayenizde oturdu o da. Oldukça güzel niteler. Belirteç demeye devam :-)
acehreli;
Örneğin, 'double' ve 'in double' çağıranın açısından aynı anlamdalar çünkü ikisinde de çağıranın değişkeni değiştirilemez. Ama tabii ki 'in double' yeğlenmeli çünkü parametre hakkında daha fazla bilgi taşıyor.
Katılıyorum. Yeri geldikçe uygulamaya devam.
Salih:
Ancak şimdi assembly kodlarını inceleyerek bunun biz programcılar için sadece bir takı olduğumu yoksa bir araç ve gereç gibi bir işi yapan belirteç mi olduğundan emin olabilirim. Konuyu çok şişirmemek için hemen aşağıda iletimi düzenleyerek cevaplayacağım:
Çok güzel. Demek ki dağarcığımız genleşecek. Salih hocam bulgularını bekliyorum.
Bu aşamadan sonra yavaş yavaş yapı haline döndürebileceğiz belki de programı.
mert
Bu mesaj mert tarafından değiştirildi; zaman: 2012-10-19, 15:44.
acehreli (Moderatör) #18
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ı
Yanıtlanan mesaj #16
Salih Dinçer:
in ile const arasında hiç bir fark yok!

Aslında var ama derleyiciler scope'u henüz desteklemiyor: in, 'const scope'un eşdeğeri. Yani hem değiştirilemez (const), hem de işlevden dışarıya kaçırılamaz (scope).

kullanmadığımız zaman parametre değişkenlerine bellekte farklı bir şekilde yer ayrılıyor

Orası derleyicinin bileceği iş. :) Tabii biz bu belirteçlere anlamsal açıdan yaklaşmalıyız.

Ali
Avatar
mert #19
Üye Ara 2010 tarihinden beri · 194 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Bu tartışma şekillenirken aklıma püf noktalarına eklenebileceğini düşündüğüm bir şeyler geliverdi.

Acaba: "Eğer gelişmekte olan bir programlama dilinde %100 aynı işi yaptığına inandığımız   olanaklardan iki adet varsa, bunların bir tanesi ya gerçekten diğerinden farklı işler yapıyordur veya biri emekliye ayrılmak üzeredir." demek ne kadar doğru olur veya mantıklı mıdır?
mert
Avatar
Salih Dinçer #20
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Örneğin clean() yerine gelen destroy() 2.060'da clean'nın yılbaşında emekliye ayrılacağını söylüyor. Ayrıca bir süre hata olmasın diye alias ile clean'ı destroy'a bağlamışlar.

Bir de yukarıdakilere benzer delete() var ki aynı gibi görünse de ek olarak bellekten de temizliyor. Yani an itibariyle destroy() ve delete() birbirine benzese de destroy() ile sildiğimiz nesneyi GC'ye emanet ederken, delete()'de ise onun yerine siliyoruz. Bu sefer de yüksek sayıdaki işlemlerde yapılan bu belleğe boşaltma işlemi bize ek zaman kaybı anlamına geliyor.

Özetle göründüğü gibi olmayan şeyler var ama in ile const 2.059 için birebir aynı olduğuna yemin bile edebilirim...:)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #21
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ı
Yanıtlanan mesaj #19
mert:
Acaba: "Eğer gelişmekte olan bir programlama dilinde ..."

Zararı yok ama gerek de yok.

Ali
Avatar
mert #22
Üye Ara 2010 tarihinden beri · 194 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Salih:
Özetle göründüğü gibi olmayan şeyler var ama in ile const 2.059 için birebir aynı olduğuna yemin bile edebilirim...
Sizler kadar deneyimli değilim. Ancak genelde in belirtecini işlev parametrelerinde kullanmaya aşinayız. const ise çoğunlukla pek çok durumda kullanılıyor. Belki de ek fark birinin diğerine göre daha geniş kapsamlar için kullanılıyor olmasındadır. (const)
Bu durum bile benim const'u ayrıcalıklı bir konuma yerleştirmeme yetiyor.
Şuradaki bilgi benim için şu aşamada yeterli:
http://ddili.org/ders/d/islev_parametreleri.html  dersi in belirteci konusu
in anahtar sözcüğü parametrenin bu düzenekte yalnızca bir giriş bilgisi olarak kullanıldığını belirler. Bu tür parametreler işlevde yalnızca bilgi olarak kullanılırlar, kendileri değiştirilemezler. in bu açıdan const'a benzese de, İngilizce'de "içeriye" anlamına geldiği için, parametrenin amacını daha açık bir şekilde ifade eder:
Gayet açık, gayet net.
acehreli:
Zararı yok ama gerek de yok.
Gerek yoksa atlanır. Hiç ikilenmez.
mert
Bu mesaj 2 defa değişti; son değiştiren: mert; zaman: 2012-10-19, 14:41.
Avatar
mert #23
Üye Ara 2010 tarihinden beri · 194 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj ID 8050
Konu adı: Aşama -3
Bayramı fırsat bilerek programımızı terkeden kahramanımız, epey semirmiş ve dinlenmiş olarak geriye döndüğünden ve artık onun diğer silahlarını da başarıyla kullanabileceğine inandığımız yetenekli bir işlevi olduğunu düşündüğümüzden diğer ek silahları olan "kılıç, tabanca, tüfek, bomba" kullanımı ile ilgili tasarımımızı artık gerçekleştirebiliriz.

Kahramanımızın bayramda ceplerini parayla doldurmuş olduğunu bildiğimizden (büyüklerin elleri, küçüklerin gözleri:-), hazır kendisine ek olanaklar sağlamaya kalkışmışken, kendisine bu parayı oyunun içinde kullanma şansını da tanımamız gereksin.

Bu durumda kahramanımız; hem düşmanları ile karşılaşırken aldığı darbelerde enerjisinden ve parasından bir miktar kaybedecek, hem de ilerleyen aşamalarda elindeki parayı da kullanarak elde edeceği "bisiklet, motosiklet, atv, pikap, tank" gibi araç gereçlerini kullanacak.

Peki bu durumda programımı nasıl gerçekleştirebilirim?:

1 - Kahramanımın edinebileceği; bıçak, kılıç, tabanca, tüfek, bomba silahlarını ve bisiklet, motosiklet, atv, pikap, tank gibi araçlarını kullanabilmek için isimli sabit değerlerden yani enum'dan yararlanabilirim.
2 - İkinci aşamada tanımladığım işlevi bıçakDarbesiniHesapla() yerine, enerjisiniHesapla() olarak yeniden düzenlersem, kahramanımızın vurduğu/aldığı darbeleri bu işlevde hesaplattırır kazandığı/ kaybettiği enerji değerlerini ölçebilirim.
3 - Benzer bir ek işlev daha tasarlayıp kazandığı/kaybettiği para değerlerini de ona hesaplattırabilirim. Onun adına da parasınıHesapla() deyip geçiveririm.

Böylece iki işlev ve bir enum türü ile programımın şimdiki bölümünü tasarlayabilirim.

Hımm, işe yarar görünüyor. Deneyelim görelim:
import std.stdio;
 
enum DarbeTipi { Bıçak = 10, Kılıç = 25, Tabanca = 55, Tüfek = 70, Bomba = 90 }
 
double enerjisiniHesapla (in double enerji, DarbeTipi darbe)  //[1]
{
    double enerjiÖlçeği = enerji - (darbe * 1_000);
    return enerjiÖlçeği; 
}
 
double parasınıHesapla (in double para, DarbeTipi darbe)      // [1]
{
    double paraÖlçeği  = para - (darbe * 500);
    return paraÖlçeği;
}
 
void main()
{
    double kahramanınEnerjisi = 100_000;
    double kahramanınParası   = 100_000;
    enum darbe                = DarbeTipi.Bomba;
 
    double kahramanEnerjisi   = enerjisiniHesapla(kahramanınEnerjisi, darbe);
    double kahramanParası     = parasınıHesapla(kahramanınParası, darbe);
 
    writeln("Kahramanın Enerjisi : ", kahramanEnerjisi);
    writeln("Kahramanın Parası   : ", kahramanParası);
}

// Kahramanın Enerjisi : 10000
// Kahramanın Parası   : 55000


 Evet ama, daha düşmanın enerjisi ve parasını hesaplayacağım değil mi? Hem kahramanımız sadece bir düşman ile karşılaşacaksa bunun adı da oyun olmaz zaten. Çok sayıda ve farklı yeteneklerde, farklı araç gereçler kullanan düşmanlardan söz edeceksek eğer, ben her karakterin sadece para ve enerji durumları için bile iki farklı işleve başvurmalıyım.
Yine ayrıca işlevlerim tamı tamına birbirinin aynısı. Yani aslında temelde yapılan iş bir adetken ben bu işi iki ayrı işlev kullanarak yapabiliyorum.
Bu sorunun olası bir çözümü de tek bir işlev kullanarak   hem enerji hem para değerlerini o işleve hesaplattırmak ve elde edilen enerji ve para değerlerini bir dizi halinde döndürüp gerektiğinde kullanmak.

Ancak bu defa da, kodlarım olması gerekenden daha fazla karmaşık olacak ki, programımızda sade bir yapı istediğimizi en başından söylemiştik.

Yeterince palazlandığımız başka nasıl belli olacak?

[1] Dikkat edileceği gibi aslında her iki işlevimizde aynı işi yapmakta.

İlgi: http://ddili.org/ders/d/yapilar.html
mert
Bu mesaj 2 defa değişti; son değiştiren: mert; zaman: 2012-10-28, 20:01.
acehreli (Moderatör) #24
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ı
Yine herhalde ileride geliştireceksindir ama ben yine de karışayım. :)

DarbeTipi'ni bir tür olarak kullanıyorsun ve zaten de öyle olmalı. Ancak, bu türün değerlerinin o türün bütün sorunlarını çözebilmesi biraz şans oluyor. Örneğin, o türün enerjisi değerinin bin katı olarak ve parası değerinin beş yüz katı olarak hesaplanabiliyor. Tabii ki bu genel hesap her tür için doğru olmayabilir.

O yüzden herhalde daha sonra sınıflar kullanarak NYP'ye geçeceksin. (?) O zaman her tür kendi özel değerlerini üye işlevlerinin dönüş değerleri olarak sağlayabilir.

Ali
Avatar
mert #25
Üye Ara 2010 tarihinden beri · 194 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Hıhım.
acehreli:
Yine herhalde ileride geliştireceksindir ama ben yine de karışayım. :)
Karışmak ne demek :-) Ne kadar katılım o kadar anlaşılırlık. Hep karışın lütfen.Her biriniz konuya katışın ki çeşitlensin. Mutlaka değinmeyi unuttuğum birşeyler kalacaktır geride. Ne kadar az kalırsa o kadar iyi. Çünkü gerekli gereksiz bir sürü soru oluşuyor kafalarda  bu aşamalarda genellikle. Nasıl yapsam sorusuna yanıt da arıyoruz.
 
Enum burada başlangıç yaklaşımı yani ilk akla gelen. Daha sınıflardan bihaberiz, eldeki olanakların yapılara kadarı öğrenilmiş, uygulanmaya çalışılıyor. Yapılar dersi, nesne yönelimli programlamayı oldukça geniş özetliyor. Aslında bBu dersin sonunda programcımızın  kafasında sizin de belirttiğiniz gibi bir ışık yanacak. Engebeli yollardan uzaklara gidilmesinin ne kadar zor olduğu anlaşılacak. vs. vs.. Hikâye yazıyoruz öte yandan :-)))

acehreli: DarbeTipi'ni bir tür olarak kullanıyorsun ve zaten de öyle olmalı.
Ona rağmen işlev içinde
 double enerjiÖlçeği = enerji - (darbe * 1_000);
gibi basit bir hesaba gerek görülmesi bile enum'un bizi yolda bırakabileceği mesajını veriyor. Olması gereken tasarım sizin şurada belirttiğiniz http://ddili.org/forum/post/3767 gibi olacak sona doğru.

Belki orada özellikler, sarma gibi yöntemlere de değinebiliriz diye düşünüyorum.
mert
Avatar
Salih Dinçer #26
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #24
mert:
Yine ayrıca işlevlerim tamı tamına birbirinin aynısı. Yani aslında temelde yapılan iş bir adetken ben bu işi iki ayrı işlev kullanarak yapabiliyorum.
Bu sorunun olası bir çözümü de
Ben bu sözlerden çok yakında (belki 4. aşamada) NYP'ya geçeceğimizi algılıyorum. Muhtemelen o zaman her şey daha güzel olacak.
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
mert #27
Üye Ara 2010 tarihinden beri · 194 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Ben bu sözlerden çok yakında (belki 4. aşamada) NYP'ya geçeceğimizi algılıyorum. Muhtemelen o zaman her şey daha güzel olacak.
Haklısın Salih hocam. Çok uzatmadan nyp'ya aktarmalıyız :-)
mert
Avatar
Salih Dinçer #28
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Merhaba,

Tartışmamızdan bu yana 1 aydan fazla zaman geçmiş...

Bakın Allah'ın işine ki ben de tam 1 aydır Legend oynuyorum; forumda bahsetmiştim. Diyebilirim ki bu tür oyunlarda uzmanlaştım. Bunlar gerçekten çok karışık şeylermiş. Görünen o ki bu tür oyunlar (Knight, Hereos, Legend, Metin2) çoğunluk tarafından seviliyor. Türü de MMOG oluyor zannedersem. Düşünsenize bir sürü oyun, sunucu, kahraman ve bir o kadar insan birbirleriyle sanal ortamda mücadele ediyor. Belki de devletler kozlarını bu ortamlarda paylaşmalı...:(
(İşte bu fikir silaha giden paranın insanları yaşatmaya, ölümlerin olduğu askerlik mesleğinin de rafa kaldırılmasına sebep olabilir!)

Neyse, konumuz yazılım olduğuna göre bu oyunlara kulağımızı kapamamız gerekiyor. Hiç grafik olaylarına girmeden bile o kadar çok kavram var ki işin içinden çıkmamız için iyi bir planlama şart. Ama temelde bir Kahraman sınıfı olmalı ve gerek düşman, gerek okçu, gerekse büyücü gibi karakterler (bu dünyada Caesar veya Lord diyorlar) bundan türeyebilmeli. Şöyle basit bir örnek hazırladım:
class Kahraman {
    real can = 100.0;   // can > 0 ise yaşıyor
    ubyte seviye = 1;   // can * seviye = gerçek gücü (HP)
    uint savunma = 1;   // reserved (sihire karşı olabilir?)
    uint saldırı = 1;   // büyücüde sihirli saldırı olacak
    
    this(int savunmaGücü, int saldırıGücü, int hasarOranı) {
        this.can = (can * cast(real)seviye)
                        * cast(real)savunmaGücü;
        this.savunma = savunmaGücü;
        this.saldırı = (hasarOranı * cast(uint)seviye)
                                   * saldırıGücü;
    }
    
    bool vur(Kahraman k) {
        if(can > 0) {
          k.can -= cast(real)saldırı;
          return false;
        }
        return true;
    }
    
    bool yaşıyor_mu() {
        return can > 0;
    }
    
    void sonrakiSeviye() {
        saldırı *= ++seviye;
    }
    
    string toString() {
        string durumu = format(" canı %.0f ve ", can);
            
        if(yaşıyor_mu) durumu ~= "yaşıyor...";
        else durumu ~= "yaşamıyor.";
        
        return durumu;
    }
}
 
  import std.stdio, std.string;
  
void main() { // savunma ----v   v---- saldırı
    auto okçu = new Kahraman(40, 40, 5); // <---- hasar
    auto kurt = new Kahraman(10, 10, 5);
    
    kurt.sonrakiSeviye// kurt level 2;
    kurt.sonrakiSeviye// kurt level 3;
    //kurt.sonrakiSeviye;  // kurt level 4;
    
    while(true) { // musabaka döngüsü (test amaçlı)
      if(okçu.vur(kurt)) break;
      if(kurt.vur(okçu)) break;
 
      okçu.can.writeln(" (okçu)");
      kurt.can.writeln(" (kurt)");
    }
    
    "Okçu".writeln(okçu);
    "Kurt".writeln(kurt);    
}
Belki de çalışan en basit kod budur. Çünkü sırayla vuruş yapılan bir düelloyu canlandırabiliyorsunuz. Eğer karakterinizin değeri iyi ise galip çıkıyor...

Ancak olay bitmiyor!

Örneğin iksir olayları var; mesela güç iksiri içerseniz, atıyorum 1 saat (iksirin etkisini yitirme süresi) boyunca hasar oranınız %2 artıyor olabilir. Aynı şekilde savunma (defence), can (HP ~ beden) vb. şeyler var. O yüzden bu sınıfın içine, zamanlama işlevi olan bir türü, dizi olarak koymamız gerekiyor. Bunu düşünüyorum...

Sonra silahlar var. Şimdi, yukarıdaki örnekte okçu kullandığım için (kurtun da dişleri var) çok ayrıntıya girmemiş oldum. Ancak kasktan tutun da üzerinize taktığınız aksesuara kadar (biz buna eşya yani item diyelim) çok şey var. Her birinin herhangi bir veya daha fazla özelliğinize olumlu etkisi var. Belki bunlar işin ilgi çeken ayrıntısı. Ama silah ile donatmak veya donatılanı başka bir değerli eşya ile değiştirmek önemli. Böylece sonsuz çeşitlikte karakterler oluşuyor!

Neyse, o kadar çok şey yazabilirim ki vaktinizi almayayım. Onun yerine bir soru sorayım: Bu kahraman bir okçu değil de büyücü olsaydı sınıfı ilerisi için nasıl olgunlaştırırdık?

Ek bilgi de vereyim. Büyücülerin saldırısı yerine sihirli saldırısı var ve doğal olarak da sihirli savunması. Aslında her karakterin sihirli savunması var. Çünkü rakip (düşman) sihir yapabilir. Örneğin cinler, periler geliyor. Hatta bunlar birden fazla geliyor!

Dip Not: Sonraki aşama ordu kavramı olabilir? Öyle ki her bir kahraman diğer kahramana birleştiriliyor. Bir ekip oluyorsunuz ve oyunda tek karakter olarak görünüyor. Bunu da pratik bir şekilde çözebileceğimizi düşünüyorum.

Başarılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #29
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ı
İsimlerine bakarsak, Kahraman üst sınıf, Okçu, Büyücü, vs. de alt sınıf oluyor. Önemli olan hangi işlemlerin ve verinin her Kahramanda mutlaka buldunduğunu belirlemek ve onları Kahraman düzeyinde gerçekleştirmek. Her kahramanın özel işlemleri ve verileri de o özel kahraman düzeyinde gerçekleştirilebilir.

Yukarıdakiler en temel kavramlar. Bunların üzerine yararları görüldükçe design patterns da uygulanabilir.

Benim sıradüzenlerde karşılaştığım bir yapı şöyle:

           Kahraman
               |
         KahramanOrtak
           /      \
   İksirleÖlen  İksirleGüçlenen  (bu düzey ve alttaki böyle olmak zorunda değil)
   /   /   \       /    \
Okçu ...  ...    ...    Büyücü


  • interface Kahraman: Bir interface. Burada her kahramanda olan ve oyunda gereken bütün işlemler bulunur: karşılaş(Kahraman k), yaşıyor_mu(), iç(Eşya e), al(Eşya e), vs.

  • class KahramanOrtak: Her kahramanda bulunan ortak özellikler buradadır. Örneğin her kahramanın canı varsa buraya gelebilir: real can, real seviye, vs.

  • class İksirleÖlen ve İksirleGüçlenen: iç() işlevine İksir geldiğinde can=0 olur veya olmaz.

  • class Okçu, Büyücü, vs. Bunlar her kahramanın en özel işlemlerini ve verilerinin tutarlar.

Yukarıda en alttaki iki düzey aslında öyle olmak zorunda değil. İksirleÖlen veya İksirleGüçlenen gibi ikili (veya çoklu) ayrımlar sıradüzende düzey olamazlar çünkü onun gibi bir çok farklı olanak bulunabilir.

iç(Eşya e) işlevine tekrar bakarsak, belki de bir yöntem, bu türlere belirli eşya içildiğinde ne olacağını anlatan işlevleri kurucularında vermektir:
class Okçu : KahramanOrtak
{
    this(/* ... */)
    {
        // ...
        super.içmeEtkisiEkle(new İksirleÖlme(/* ... */));
    }
    // ...
}
KahramanOrtak'a yapılan o çağrı, KahramanOrtak'ın "içince neler olsun" bilgisini tutan diziye bir bilgi ekler. Eğer iç(Eşya e) işlemi KahramanOrtak düzeyinde gerçekleştirilirse, eldeki "neler olsun" dizisinde ilerlenir ve bu kahramanda gereken değişiklikler yapılabilir.
class KahramanOrtak : Kahraman
{
    real can;
    İçmeEtkisi[] içinceNelerOlsun;
 
    void içmeEtkisiEkle(İçmeEtkisi ii)
    {
        içinceNelerOlsun ~= ii;
    }
 
    void(Eşya e)
    {
        foreach (etki; içinceNelerOlsun) {
            etki.etkile(this, e);
 
            if (!yaşıyor_mu()) {
                break;
            }
        }
    }
 
    // ...
}
Garip ayrıntılara daldım ama umarım kahramanlar arasındaki farklılıkların nasıl her tür tarafından bilinmesinin gerekmediğini gösterebilmişimdir. Her ne kadar kahramanın canını KahramanOrtak yönetiyor bile olsa, aslında iksir içince ölünme kavramından onun bile haberi yok. Onun tek bildiği, bir eşya içince bazı etkilerin olabildiği. Tek yaptığı, içilen eşyayı (ve kahramanın kendisini) o etkilere geçirmek ve onların kahramanı etkilemesini sağlamak.

Tabii onun işleyebilmesi için İçmeEtkisi'nin de bir interface olması çak yararlıdır:
interface İçmeEtkisi
{
    void etkile(Kahraman k, Eşya e);
}
 
class İksirleÖlme : İçmeEtkisi
{
    void etkile(Kahraman k, Eşya e)
    {
        // Eğer içilen bir İksir ise k'nin canının sıfır yap
        // Hatta, belki de Kahraman'ın asıl türüne göre farklı etki bile yapılabilir.
    }
}
NYP'nin sorunlu taraflarından birisi de tam o noktada başlar. Veya şöyle söyleyelim: çoğu NYP dilinde bulunmayan bir olanak tam o noktada gerekir: Yukarıda etkile() içinde İksirleÖlme sınıfında olduğumuzu biliyoruz. Yani eşya bir İksir olduğunda kahramanı öldüreceğiz ama elimizde yalnızca bir Eşya var. Onun İksir olduğunu nasıl bilebiliriz?

Tekrar bakalım: etki.etkile(this, e) yapılan yerde tek bir türe göre havale yapılmıştır. Dil bize tek tür üzerinde havale olanağı sunmuştur: etki'nin asıl türü (çalışma zamanındaki türü, dinamik türü) İksirleÖlme olduğu için programın akışı İksirleÖlme.etki() işlevine geçmiştir. Ama görüldüğü gibi, bu tek tür üzerinden olmaktadır: Program akışı Kahraman'ın ve Eşya'nın çalışma zamanındaki türlerine bağlı olmamıştır. NYP'de bu sorunun adı "double dispatch"tir (hatta bu durumda belki de "multiple dispatch").

Double dispatch C++ veya D tarafından sağlanmaz (başka dillerde var mı, bilmiyorum). Bunun çözümü programcının görevidir. Bir çözüm, Eşya'nın typeid'sine bakmak ve İksir ise ona göre davranmaktır. typeid Eşya'nın çalışma zamanındaki asıl türünü verir. Ama bu bilgiye bakma gereği, saf NYP'den uzaklaşma anlamına gelir ve dilin yetersizliği olarak görülür.

Ama bunlar göz korkutmasın. Ben saf NYP uygulandığında karşılaşılabilecek bir sorun olarak gösterdim. Başka çözümler de bulunabilir. NYP'de (OOP'de) "Double dispatch"i araştırmak gerek.

Temellerimize dönersek, bu gibi işler NYP'nin olmadığı C gibi dillerde bile yapılabildiğine göre aslında o kadar zorlamaya gerek yok. Belki de en basit yöntem neyse onu uygulamak en iyisi... :)

Ali
Avatar
Salih Dinçer #30
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Hocam çok güzel yazmışsın eline sağlık...

Ben zannedersem, daha basit bir yapı düşünüyorum ama interface konusunu unutmuşum; neden olmasın! Zaten bir süre sonra böyle bir yapı kaçınılmaz olacak. Ama konunun gelişimi açısından basit parçalar ile yola devam etsek nasıl olur?

Örneğin zamanlama konusunda bugün şöyle bir şey yazdım: http://dpaste.dzfl.pl/4018d6c4

Aynı şekilde süresiz eşyalar, zaman damgası olmadan da kullanılabilir. Aslında daha eklenecek çok şey var. Bunlardan biri de durumuYedekle() ve geriYükle() gibi iki üye işlev. Çünkü musabaka öncesi güncel durum yedeklenip bittiğinde geri yüklenmesi gerekiyor. Bu tür oyunlar çok elli musabakalar şeklinde düzenlendiği için böyle bir kural var...

Mert Hocam, sen ne düşünüyorsun? Hızlı girmedik inşaallah...:D
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
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:
Sayfa:  önceki  1  2  3  sonraki 
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-21, 15:19:44 (UTC -08:00)