RPG Oyununu Geliştirmek

Kitapta da geçen, RPG türünde oyun var. Oyunun işleyişi şu şekilde:
-Canavar ve sen varsın yani oyunu oynayan kişi.
-Bir başlangıç ekranında ki yaklaşık şöyle:
Rakip ile karşı karşıyasın.
Yapabileceğin hamleler:
Saldır (s)
Kaç (k)
Çık (ç)
Ne yapmak istersin? şeklinde başlıyor.
-3 farkı ihtimal dahilinde yani:
Rakip vurabilir,
Oyuncu vurabilir,
Kimse vuramaz, şeklinde oyun ilerliyor.
-Bir darbe değişkeni var ki darbe aldığın kadar artıyor. 5 darbede 1 canın azalıyor ki canın 5.

Benim isteğim bu oyunu geliştirmek. Oyunun kodlarına bazı eklemeler yaparak denedim ama IDLE Phyton “galiba” verebilecek hata bulamadığı için “Burada boşluk var. Kabul edilemez” gibi yersiz hatalar veriyor.
Yazarın kodlarını şuradan bulabilirsiniz:
https://belgeler.yazbel.com/python-istihza/nesne_tabanli_programlama3.html#basit-bir-oyun

Bu da benim ekleme yaparak geliştirmeye çalıştığım kodlar:

import time
import random

class Oyuncu(Oyuncu_Özellikleri, Köy, Dev, Çapulcu, Hayalet, Goblin, Mağara):
    def __init__(self, isim, can=100 ,vuruş=5, enerji=10):
        self.isim = isim
        self.can = can
        self.vuruş = vuruş
        self.enerji = enerji

def ihtimal(self):
    değer = random.randint(1, 5)
    if değer == 1:
        self.Köy()
    if değer == 2:
        self.Dev()
    if değer == 3:
        self.Çapulcu()
    if değer == 4:
        self.Hayalet()
    if değer == 5:
        self.Goblin()
    if değer == 6:
        self.Mağara()

def savaş(self):
    ne_olsun = input("Saldırı için's'ye,\nKaçmak için 'k'ye,\nÇıkmak içinse 'q'ya basınız...")
    if ne_olsun == "s":
        self.saldır()
    if ne_olsun == "k":
        self.kaç()
    if ne_olsun == "q":
        self.çık()


def mevcut(self):
    print("Canınız:\t", self.can)
    print("Vuruş Gücünüz:\t", self.vuruş)
    print("Enerjiniz:\t", self=enerji)

def saldırı_sonucu(self):
    return random.randint(0,2)

def saldır(self, rakip):
    print("Bir saldırı gerçekleştirdiniz.")
    print("Saldırı sürüyor, bekleyiniz.")

    for i in range(10):
        time.sleep(0.3)
        print(".", end="", flush=True)

    sonuç = self.saldırı_sonucu()

    if sonuç == 0:
       print("\nKazanan Taraf Yok!\n")

    if sonuç == 1:
        print("\nRakibinize Vurmayı Başardınız!\n")
        self.vur(rakip)

    if sonuç == 2:
        print("\nRakibinizden Darbe Aldınız!\n")
        self.vur(self)


def vur(self, darbelenen): 
    darbelenen.can -= vuruş
    if darbelenen.can < 1:
        print("Bu bölüm de bitti!") 
        self.ihtimal()

def kaç(self):
    print("Kaçmaya çalışıyorsunuz...")
    time.sleep(3)
    kaçma = random.randint(1,3)
    if kaçma == 1:
        print("Rakibiniz sizi yakaladı!")
    if kaçma == 2 or 3:
        print("Kaçtınız!")
        ihtimal()

def çık(self):
    print("Oyundan çıkılıyor...")
    time.sleep(2)
    quit()
            


class Köy():
    def __init__(self):
        print("Köyümüze Hoşgeldiniz tabelası göründü...")
        iş = input("Dinlenmek için 'd',\nİnsanlar ile konuşmak için 'k'ye basınız...")
    
def dinlen_köy(self):
    self.can += 10
    self.enerji += 2

def köylü(self):
    Bir = print("Merhabalar.İlerde han var, burda başka bir şey de yok!")
    İki = print("Size yardımcı olamam çünkü ben de buralarda yeniyim...")
    Üç = print("Hanımız her zaman emrinize amadedir.",
               "Bizler sizin gibi gezginler sayesinde varız...",
               "Ancak öyle para...Neyse ben ne anlatıyorum ki...")
    Dört = print("Sizin gibilerden NEFRET EDİYORUM!!!ŞİMDİ GİDİN BURDAN!")
    Beş = print("Buralarda çok canavar var değil mi?")

    köylü_liste = [Bir, İki, Üç, Dört, Beş]
    köylü_liste_sonucu = random.choice(köylü_liste)

if iş == "d":
    dinlen_köy()
if iş == "k":
    print(köylü_liste_sonucu)    

class Dev():
def __init__(self, can=20, vuruş=10, enerji=4, rakip=):
    self.can = can
    self.vuruş = vuruş
    self.enerji = enerji
    print("Bir 'Dev' size doğru geliyor...")
    self.savaş()

  

class Çapulcu():
def __init__(self, can=15, vuruş=15, enerji=6):
    self.can = can
    self.vuruş = vuruş
    self.enerji = enerji
    print("Bir 'Çapulcu' bıçağıyla beraber karşınızda!...")
    self.savaş()

class Hayalet():
def __init__(self, can=10, vuruş=10, enerji=4):
    self.can = can
    self.vuruş = vuruş
    self.enerji = enerji
    print("Bir 'Hayalet' uçarken taklalar atarak yaklaşıyor...")
    self.savaş()

class Goblin():        
def __init__(self, can=5, vuruş=10, enerji=2):
    self.can = can
    self.vuruş = vuruş
    self.enerji = enerji
    print("Bir 'Goblin' sallana sallana yürümeye çalışıyor...")
    self.savaş()

class Mağara():
def __init__(self):
    print("Bir 'Mağara' ile karşılaştınız.")
    print("Uyumak istiyorsanız 'u'ya \n İlerlemek istiyorsanız 'i'ye basınız.",
          "Ancak unutmayınız ki uyurken baskına uğrayabilirsiniz.",
          "Ama mağara handan daha iyidir...") 
    mağara_istek = input("Ne yapmak istersiniz?\t")

    if mağara_istek == "u":
        dinlen_mağara()
    if mağara_istek == "i":
        print("", end="")

    mağara_ihtimal = random.randint(1,3)
    if  mağara_ihtimal == 1:
        saldır()

class Oyuncu_Özellikleri():  ####__init__ fonksiyonu "Oyuncu" classına miras alınabilsin diye... 
def __init__(self, isim, can=100 ,vuruş=5, enerji=10):
    self.isim = isim
    self.can = can
    self.vuruş = vuruş
    self.enerji = enerji



#Oyuncu kısmı
ad = input("Oyundaki adınız:\t")
siz = Oyuncu(ad)

while True:
ihtimal()   #Tıkandım 

İncelenirse bir “ihtimal()” fonksiyonu içerisinde bulunan classlar farklı bir yerden tanmlanıp, başka bir class’ta miras alınmaya çalışılmış. Kitapta geçtiğine göre çoklu miras almada ilk miras alınan class’ın “init” fonksiyonu miras alan class’a verilirmiş ancak o örnekteki class boş…
Belirlenen classlar da yaratıklar, köy ve mağara (Mağara olmasa da olur bir ihtimal daha eklensin diye koydum.) olmak üzere toplam 6 tane yani 6 farklı ihtimal var. Eğer yapılabilirse yaratıkları yani “yaratık classları” rastgele birleştirilerek (ya da belirli bir şekilde) farklı değişkene atanarak oyuncunun karşısına koyulabilir. Eğer “Tkinter” ile yapılabilirse çok daha gelişmiş bir ürün olabilir ancak benim Tkinter bilgim neredeyse olmadığı için çok geniş bir araştırma yapmadan kodları oluşturmam oldukça zor.
Eklemeliyim ki kodlarda pekala mantık hatası olabilir ya da belki bir parantez…
Şimdiden teşekkürler :blush:

Şu anda kodlarınız forum mesajınızda dağınık halde duruyor. Kodlarınızın tamamının başına ve sonuna ``` işareti ile koyarak mesajınızı düzenlerseniz yardımcı olmamız kolaylaşır. (Bkz. Forumda kod paylaşılırken kullanılan yöntemler)

Geri bildiriminiz için teşekkürler. Ben de daha sonra baktığımda fark ettim…
Şu an da düzgün.

Furkan noreply@forum.yazbel.com, 5 Ağu 2018 Paz, 18:14 tarihinde şunu yazdı:

Kodlarınızı inceledim. Sanıyorum ki daha OOP (Nesne tabanlı programlama) kavramına yeni başlamışsınız. Hatalarınızın bazılarını madde madde inceleyerek açıklamaya çalışayım:

  • İlk olarak Python’un çalışma mantığını hatırlayalım. Python yazdığımız kodları yukarıdan aşağı doğru okur. Yani eğer:
print(a + b)
a = 5
b = 4

Şeklinde bir kullanımda Python bize a ve b değişkenlerinin tanımlanmadığı hatasını verir. Aynı şekilde sizin kodlarınızda:

import time
import random

class Oyuncu(Oyuncu_Özellikleri, Köy, Dev, Çapulcu, Hayalet, Goblin, Mağara):

Oyuncu sınıfının miras alınacağı sınıflar daha tanımlanmamış olduğu için hata alırsınız.

  • İkinci olarak örneğinizdeki Oyuncu sınıfına Köy, Dev, Çapulcu, Hayalet, Goblin, Mağara sınıflarını miras almanıza hiç gerek yok. Miras almanın amacı o sınıfın değişkenlerini örnek aldığınız sınıfa uygulamaktır. Sınıflardaki sınıf değişkenlerini kullanarak diğer sınıfların da bu değişkenlere daha sınıf örneklenmeden ulaşabilmesini sağlayabilirsiniz.

  • Sınıf içindeki örnek değişkenlerini başında mutlaka özel ifadesiyle yazıyoruz. Sizin örneğinizde “self” bu özel ifade oluyor. Ayrıca başka sınıfın değişkenine ulaşırken “self” ifadesini kullanamazsınız. Sizin örneğinizde:

class Dev():
    def __init__(self, can=20, vuruş=10, enerji=4):
        self.can = can
        self.vuruş = vuruş
        self.enerji = enerji
        print("Bir 'Dev' size doğru geliyor...")
        self.savaş()

sınıfında (diğer sınıflarda da aynı hata var) “self.savaş()” ifadesi hatalı çünkü “Dev” sınıfında “savaş()” fonksiyonu yok. Bu, “Oyuncu” sınıfının fonksiyonu. Ayrıca bu haliyle bu fonksiyonu başka sınıflarda çağıramazsınız çünkü henüz “Oyuncu” sınıfı örneklenmemiş oluyor. Sınıf metodu olarak yeniden tanımlanmalı.

  • Son bahsettiğim durum değişkenlerde de geçerli. Yani:
def dinlen_köy(self):
        self.can += 10
        self.enerji += 2

ifadesinde “Köy” sınıfı “can” ya da “enerji” değişkenlerine sahip değil. Bunlar, “Oyuncu” sınıfının değişkenleri.

Size tavsiyem “Sınıf” konusunu ve tekrar çalışmanız ve kodlarda ekleme yapmadan önce nasıl çalıştığını çözmeniz. Çünkü kodlarınız bu durumdayken çok eksik ve yanlışları var.
Kendinizi ekleme yapmaya hazır hissettiğinizde eklemelerinizin hepsini bir anda değil, sırayla yapın. Yani pek çok özellik eklemektense önce birini ekleyin ve iyice test edin. Sorun olmadığına emin olduğunuzda diğerlerine geçersiniz.

Size önerim pylint kullanabileceğiniz bir editöre geçin. Şu gönderiye bir göz atın.

Öncelikle cevabınız için çok teşekkürler. Ben bu kodları nesne Tabanlı Programlama’yı bitirdim zaman yazmıştım. Ancak şu an kitabı bitirdim. Siz dedikten sonra bir daha bakınca birçok hatalamın farkına vardım ve yine dediğiniz gibi Sınıflar ve Miras Alma konularına kesinlikle bir daha bakacağım.
Eklemem gerekirse bahsettiğiniz “Phyton’un çalışma mantığını” unutmuşum ya da yanlış biliyormuşum.
Bana ders oldu.
Ben kodları daha düzgün yazıp yardıma ihtiyacım olduğu ya da çalıştığı zaman tekrar Forum’da paylaşacağım.Tekrardan teşekkürler…

Rica ederim. Oluyor bazen, küçük ama önemli detaylar gözden kaçabiliyor. Kolay gelsin :slight_smile: