Android İçin Online Satranç Oyunu

2Asgard Projesi için yazdığım Android uygulaması, proje yalan olunca ne zamandır elimde bekliyordu. Bu hali, geliştirilmeye açık olduğuna inandığım baştan yazılmış şekli. chess.py’nin yapımcısından da, öğrenci projesinde kullanılacak diye izin aldım. Benim düzenlediğim hali ile orijinali arasında, eklenen pek bir kod olmasa da çıkan çok kod oldu. Satranç notasyonunu basitleştirmek adına, chess.py’nin notasyon parse eden kısımlarını kırptım ve Android uygulamasına direk bağladım.

1Yenilikler:

– Artık karşı tarafın taşlarını elleme hakkınız yok. Bunun zaten ilk sürümde de olması gerekiyordu, geç de olsa geldi. Konsolda uyarı mesajı da veriyor, rahatsız olanlar yorum satırı yapabilir.

– Seçilen taşın arkaplanı siyah oluyor, hangi taşın seçildiği artık belli.

– Taş, istenilen yere gidemiyorsa yanan arkaplan eski haline dönüyor.

– Girenleri 2’li olarak ayrı odalara atıyor(odadan çıkan olursa diye bir önlem almadım, proje amacı sadece 2 kişinin oynamasıydı ve bu bile fantezi oldu). Binlerce kişi aynı anda oyunu oynayabilir.

– Siyah ya da beyaz taraf seçme özelliği geldi. Kullanıcılar istedikleri tarafta yer alarak buna uygun odaya yerleştiriliyor.- Bu saydıklarımla uğraşmak istemeyenler için de sadece tek oyunun döndüğü ve giren herkesin seçtiği tarafı oynatabildiği bir sunucu sürümü de hazırda var.

– Sunucuyu çalıştırdığınız bilgisayarda Python’un daemon modülü yüklü olursa iyi olur, sunucu arkaplanda çalışabiliyor. Böylece SSH’ı sunucu çalıştığı sürece açık tutma derdi kalmadı.

– Sunucu için herhangi bir kütüphane vs. kullanmadığım için hata ayıklamayla yeteri kadar ilgilenememiş olabilirim, ama henüz bir sıkıntı çıkarmadı. Profesyonel bir amaç için twisted kütüphanesiyle güzel bir düzenlenmesi gerekebilir.

– Sunucu dosyası çağırılırken python sunucu.py şeklinde çağırılırsa varsayılan olarak 4444 portundan sunucuyu başlatır. Bu port, oyunda da 4444 olarak ayarlıdır. Değişiklik yapmak isterseniz ya da aynı anda birden çok sunucu çalıştırmak isterseniz python sunucu.py PORT şeklinde çalıştırabilirsiniz(örnek: python sunucu.py 4445).

– Sunucu1, gelen veriyi belirttiğiniz fonksiyona yollar ve ona göre işleyip geri döndürür. Yani bir fonksiyon tanımlayıp gelen argümana istediğiniz veriyi atar, returnden de istediğiniz veriyi istemciye yollayabilirsiniz. Bu işlemleri sizin için yürüten SunucuAyar() sınıfıdır.

– Sunucu2, gelen veriyi, yine SunucuAyar() isimli sınıfı örneklerken belirttiğiniz sınıfı örnekleyerek, sunucu çalıştırıldığında o sınıfın baglantibaslat() fonksiyonunu, bir veri geldiğinde yine aynı sınıfın isle() fonksiyonunu çağırır. Bu sayede, bu sınıf tek bir kez örneklenerek tüm odaların bilgileri bu sınıfın örneğinde tutulmuş oldu. Yani sunucuayar sınıfı her seferinde ayrı ayrı örnekleme yapacak kadar özelleştirilmedi.

– Oyunun içinde kullanmak için hazırladığım bir diğer kütüphane ise, sunucuya bağlanmak için Twisted modülüne ufak tefek sunucular için bir arayüz sunuyor. BaglantiYonet() sınıfına cagir, gelen, kayip olarak 3 fonksiyon gönderilerek bu sınıf örneklendiğinde, fonksiyonları uygun durumlarda çağırıyor. Fonksiyonların iç dökümantasyonlarını da elimden geldiğince detaylı yazmaya çalıştım.

– Asgard.kv dosyasını yazdığımdan uzun bir süre geçtiği için şu an çok açıklayamıyorum. Ancak görünümleri, taşların konumları gibi ufak tefek ayrıntıları ayarlıyordu.

– Son olarak main.py, 2 madde üstte belirttiğim baglantiyonet() sınıfını kullanarak sunucuya bağlanıyor. main.py, telefonlar sık sık güncellenmesin diye işin büyük bölümünü sunucuya bırakmış durumda. Yani oda açan ya da açmayan sunucuyu çalıştırmış olmanız main.py için bir önem taşımıyor. Bunun çalışması için de kivy kütüphanesinin bilgisayarınızda yüklü olması gerekiyor. Bu kütüphane varken Windows, Linux ya da MacOS altında uygulama çalışıyor. Ayrıca, asıl amacı olan Android üzerinde de çalışıyor. Şu an markete yayın hakkım olmadığı için uygulamayı imzalayamıyorum ve size .apk halini sunamıyorum. Debug halini burda vermek de anlamsız olurdu diyerek konuyu noktalıyorum. Sorularınız olursa sormaktan çekinmeyin.

Not: Satranç taşları için elimde dağıtabileceğim lisansa sahip düzgün resimler olmadığından dolayı kodun şu kısmına uygun, elinizdeki resimleri eklerseniz iyi olur(images klasöründe yer alacaklar):

# Taslarin goruntuleri yukleniyor
taslar = {"P" : "images/pawnw.gif", "p" : "images/pawnb.gif",\
          "r" : "images/rookb.gif", "R" : "images/rookw.gif",\
          "n" : "images/knightb.gif", "N" : "images/knightw.gif",\
          "b" : "images/bishopb.gif", "B" : "images/bishopw.gif",\
          "q" : "images/queenb.gif", "Q" : "images/queenw.gif",\
          "k" : "images/kingb.gif", "K" : "images/kingw.gif",\
          "." : "images/empty.gif" \
          } # Beyazlar buyuk, siyahlar kucuk

Dosyalara bakacak olursak:

#-*-coding:utf-8-*-

import socket, daemon
from thread import start_new_thread

class SunucuAyar(object):
  '''
  Asgard projesi için sunucu yönetimini basitleştirmek amacıyla yazılmış sınıftır.
  Örneklenirken gelen veriyi yorumlayıp gönderilecek veriyi döndürecek fonksiyonun adı
  parametre olarak verilmelidir.
  '''

  def __init__(self, f):
    # Soket oluşturmayı deneyerek başlayalım:
    print "Soket oluşturulmaya başlanıyor..."
    self.anahtarFonk = f
    try:
      self.soket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      print "Sunucu soketi oluşturuldu."
      self.port = 4444 # Varsayılan port 4444
    except socket.error, msg:
      print "Oluşturmada hata: ", str(msg[0]), "Hata: ", str(msg[1])

  def bilgiAl(self):
    '''
    Sunucuyu tanımlayabilmek adına hostname ve ip adresini alır.
    '''
    print "Sunucu tanımlaması yapılıyor..."
    print "Sunucu makinenin ismi ve IP adresi alınıyor: ",
    self.host = socket.gethostname()
    print self.host
    try:
      self.ip = socket.gethostbyname(self.host)
      print "Alınan ip adresi: ", self.ip
    except:
      print "Sunucu ismi çözümlenemedi."

  def olustur(self, host = ''):
    '''
    Sunucuyu oluşturur, host bilgisini değişken olarak alabilir.
    '''
    self.host = host
    print "%d portunda sunucu oluşturuluyor..." %self.port
    self.bilgiler = self.host, self.port
    try:
      self.soket.bind(self.bilgiler)
    except:
      print "Soket oluşturmada hata!"

  def baslat(self, port = 4444):
    '''
    Soketi dinlemeye başlar. Gelen her bağlantıyı listen() izin verdiği sürece dinler. (max: 2)
    Sunucu uygulamasını arkaplanda başlatır. arkaplan() fonksiyonunu threading ile çalıştırır.
    '''
    self.port = port
    self.olustur()
    print "Sunucu oluşturuldu, istemci için linke veri gönderiliyor..."
    self.istemci()
    print "Sunucu başladı. Bağlantılar bekleniyor..."
    self.soket.listen(2)
    while True: # Gelen tüm bağlantıları al ve multithreading ile işle.
      self.baglanti, self.adres = self.soket.accept()
      print 'Gelen bağlantı. Adres/Port: ', self.adres[0], ":", self.adres[1]
      start_new_thread(self.arkaplan,(self.baglanti,))
      print "Bağlantı arkaplandaki thread'e gönderiliyor..."

  def istemci(self):
    from urllib import urlopen
    try:
      adres = "http://www.ufakseyleratolyesi.com/asgard.php?"
      #urlopen("http:")
    except:
      pass
    print "istemciye mesaj ulaştı!"

  def arkaplan(self, bagl):
    '''
    Arkaplanda çalışarak bağlantının sınıfa verilen fonksiyona göre cevaplanmasını sağlar.
    '''
    print "Arkaplanda işlem çalışmaya başladı."
    while True:
      self.gelenVeri = bagl.recv(4096)
      if not self.gelenVeri:
    break
      self.gidecekCevap = self.anahtarFonk(self.gelenVeri)
      bagl.sendall(self.gidecekCevap)

  def bitir(self):
    '''
    Gerekli görüldüğü durumda soketi kapatması ve programdan sys.exit ile çıkması için
    tasarlanmıştır.
    '''
    print "Sunucu kapatılıyor."
    self.soket.close()
    from sys import exit
    exit()

# Deneme amaçlı:
if __name__ == "__main__":
  import sys
  portD = 4444
  taraf = 0
  hareketler = ["BS"]
  if len(sys.argv) > 1:
    portD = int(sys.argv[1])
  def fonk(veri):
    global taraf, hareketler
    if len(veri.split()) == 2:
      print "Gelen Hamle: ", veri
      hareketler.append(veri)
      return " "
    print hareketler
    print "Gelen: ", veri
    return "\n".join(hareketler[int(veri):])
  a = SunucuAyar(fonk)
  # Arkaplana göndermek için bu kısım kullanılacak.
  # print "Şimdi arkaplana gidiyorum"
  # daemon.basic_daemonize()
  a.baslat(portD)

Şimdi oda sistemi olan satranç sunucusu:

#-*-coding:utf-8-*-

import socket, daemon
from thread import start_new_thread

odalar  = {} # Odaları tutacak boş dict

class SunucuAyar(object):
  '''
  Asgard projesi için sunucu yönetimini basitleştirmek amacıyla yazılmış sınıftır.
  Örneklenirken gelen veriyi yorumlayıp gönderilecek veriyi döndürecek sınıfın adı
  parametre olarak verilmelidir. Sınıfın isle() fonksiyonu çağırılır.
  '''

  def __init__(self, f):
    # Soket oluşturmayı deneyerek başlayalım:
    print "Soket oluşturulmaya başlanıyor..."
    self.anahtarsnf = f()
    try:
      self.soket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      print "Sunucu soketi oluşturuldu."
      self.port = 4444 # Varsayılan port 4444
    except socket.error, msg:
      print "Oluşturmada hata: ", str(msg[0]), "Hata: ", str(msg[1])

  def bilgiAl(self):
    '''
    Sunucuyu tanımlayabilmek adına hostname ve ip adresini alır.
    '''
    print "Sunucu tanımlaması yapılıyor..."
    print "Sunucu makinenin ismi ve IP adresi alınıyor: ",
    self.host = socket.gethostname()
    print self.host
    try:
      self.ip = socket.gethostbyname(self.host)
      print "Alınan ip adresi: ", self.ip
    except:
      print "Sunucu ismi çözümlenemedi."

  def olustur(self, host = ''):
    '''
    Sunucuyu oluşturur, host bilgisini değişken olarak alabilir.
    '''
    self.host = host
    print "%d portunda sunucu oluşturuluyor..." %self.port
    self.bilgiler = self.host, self.port
    try:
      self.soket.bind(self.bilgiler)
    except:
      print "Soket oluşturmada hata!"

  def baslat(self, port = 4444):
    '''
    Soketi dinlemeye başlar. Gelen her bağlantıyı listen() izin verdiği sürece dinler. (max: 2)
    Sunucu uygulamasını arkaplanda başlatır. arkaplan() fonksiyonunu threading ile çalıştırır.
    '''
    self.port = port
    self.olustur()
    print "Sunucu oluşturuldu, istemci için linke veri gönderiliyor..."
    self.istemci()
    print "Sunucu başladı. Bağlantılar bekleniyor..."
    self.soket.listen(2)
    while True: # Gelen tüm bağlantıları al ve multithreading ile işle.
      self.baglanti, self.adres = self.soket.accept()
      print 'Gelen bağlantı. Adres/Port: ', self.adres[0], ":", self.adres[1]
      self.anahtarsnf.baglantiBaslat(self.adres[0])
      start_new_thread(self.arkaplan,(self.baglanti,self.adres[0]))
      print "Oda No: %d\nBağlantı arkaplandaki thread'e gönderiliyor..."

  def istemci(self):
    from urllib import urlopen
    try:
      adres = "http://www.ufakseyleratolyesi.com/asgard.php?"
      #urlopen("http:")
    except:
      pass
    print "istemciye mesaj ulaştı!"

  def arkaplan(self, bagl, adres):
    '''
    Arkaplanda çalışarak bağlantının sınıfa verilen fonksiyona göre cevaplanmasını sağlar.
    '''
    print "Arkaplanda işlem çalışmaya başladı."
    while True:
      self.gelenVeri = bagl.recv(4096)
      if not self.gelenVeri:
    break
      self.gidecekCevap = self.anahtarsnf.isle(self.gelenVeri, adres)
      bagl.sendall(self.gidecekCevap)

  def bitir(self):
    '''
    Gerekli görüldüğü durumda soketi kapatması ve programdan sys.exit ile çıkması için
    tasarlanmıştır.
    '''
    print "Sunucu kapatılıyor."
    self.soket.close()
    from sys import exit
    exit()

class snf():
  def __init__(self):
    self.hareketler = [] # Oda id sine gore buradan hamleler bulunacak.
    self.ipler = {} # ip:oda id şeklinde veri tutacak, direk erişim.
    self.sonID = 0 # En son gelen kullanıcının id si tutulacak.

  def baglantiBaslat(self, ip): # Baglanti aktif oldugunda uygun odaya gore oyunu baslatir.
    self.ipler[ip] = self.sonID / 2 # 2 Tanesi 1 odaya yerleşecek. Integer division.
    self.sonID += 1
    if self.sonID % 2 == 0:
      self.hareketler.append(["BS"]) # Yeni bir oda oluştur

  def isle(self, veri, adres):
    print adres, self.ipler[adres]
    hareketler = self.hareketler[self.ipler[adres]] # Dict ten oda id'sine ulaştık.
    print hareketler, adres, self.ipler[adres]
    if len(veri.split()) == 2:
      print "Gelen Hamle: ", veri
      try:
        if int(veri[-2:]) > 0 and len(veri) > 5:
          hareketler.append(veri[:5])
          return "ALINDI"
      except:
        pass
      try:
        if int(veri[0:2]) > 0:
          hareketler.append(veri[2:])
          return "ALINDI"
      except:
        pass
      hareketler.append(veri)
      return "3. durumda ALINDI"
    print hareketler
    print "Gelen: ", veri
    return "\n".join(hareketler[int(veri):])

# Deneme amaçlı:
if __name__ == "__main__":
  import sys
  portD = 4444
  taraf = 0
  # hareketler = ["BS"] # Başlama komutu verildi. ID'ler de 1 den başlayacak.
  if len(sys.argv) > 1:
    portD = int(sys.argv[1])
  def fonk(veri):
    # global taraf, hareketler
    if len(veri.split()) == 2:
      print "Gelen Hamle: ", veri
      try:
        if int(veri[-2:]) > 0 and len(veri) > 5:
          hareketler.append(veri[:5])
          return "ALINDI"
      except:
        pass
      try:
        if int(veri[0:2]) > 0:
          hareketler.append(veri[2:])
          return "ALINDI"
      except:
        pass
      hareketler.append(veri)
      return "3. durumda ALINDI"
    print hareketler
    print "Gelen: ", veri
    return "\n".join(hareketler[int(veri):])
  a = SunucuAyar(snf)
  # Arkaplana göndermek için bu kısım kullanılacak.
  # print "Şimdi arkaplana gidiyorum"
  # daemon.basic_daemonize()
  a.baslat(portD)

Ana program dosyamız olan main.py:

#-*-coding:utf-8-*-
'''
Created on 12 Oca 2013

@author: guray
'''

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.clock import Clock
from kivy.properties import StringProperty
import baglanti, chess

class YanMenu(GridLayout):
    def __init__(self, ust):
        self.ust = ust
        if self.ust.taraf == 1:
            self.taraf = "Siyah"
        else:
            self.taraf = "Beyaz"
        GridLayout.__init__(self, cols = 1, rows = 3)

# Taslarin goruntuleri yukleniyor
taslar = {"P" : "images/pawnw.gif", "p" : "images/pawnb.gif",\
          "r" : "images/rookb.gif", "R" : "images/rookw.gif",\
          "n" : "images/knightb.gif", "N" : "images/knightw.gif",\
          "b" : "images/bishopb.gif", "B" : "images/bishopw.gif",\
          "q" : "images/queenb.gif", "Q" : "images/queenw.gif",\
          "k" : "images/kingb.gif", "K" : "images/kingw.gif",\
          "." : "images/empty.gif" \
          } # Beyazlar buyuk, siyahlar kucuk

class Kutula(Button):
    # BUNA PARAMETRE OLARAK UST SINIF EKLENECEK VE ON_PRESS HALINDE SECIMKONTROL E YOLLA
    tahta_konum = StringProperty()
    tas = StringProperty()
    def hangieleman(self):
        return "images/buton1.gif"

    def ustBelirle(self, snf):
        self.tahta = snf

    def on_press(self,*k):
        print self.tahta_konum
        self.tahta.secimKontrol(self.tahta_konum)
        pass

class Tahta(GridLayout):
    def __init__(self, arka):
        '''
        Tahtayi olusturur, taslari dizmek icin tahtaGuncelle() fonksiyonunu cagirir.
        Parametre olarak "arka" ismiyle parent class i alir.
        '''
        GridLayout.__init__(self,size_hint = (0.8, 1.0)) # Ekranin 4 / 5 i tahtanin
        self.ust = arka # self.ust.oyun ile Game erisimi self.ust ile tam erisim
        self.tasbutonlar = []

        self.arka = [(1,0,1,1),(0,1,1,1)] # Arkaplan renkleri
        onceki = 0
        for i in xrange(8):
            self.tasbutonlar.append([])
            onceki += 1
            for k,j in enumerate("abcdefgh"):
                kutu = Kutula(text = " ")
                kutu.ustBelirle(self) 
                kutu.tahta_konum="%s%d" %(j,8-i) # Her karenin yeri
                kutu.id = kutu.tahta_konum
                kutu.resim_id.source = "images/empty.gif"
                onceki+=1; renk = onceki % 2
                kutu.background_color = self.arka[renk]
                self.tasbutonlar[i].append(kutu) # Taş ekleme denemesi
                self.add_widget(self.tasbutonlar[i][k])
        self.tahtaGuncelle()
        self.yanik = 0
        self.yananTas = 0
        self.hamleString = ""

    def tahtaGuncelle(self):
        abc = str(self.ust.oyun.board)
        y = abc.split("\n")[1:-2]
        for i in xrange(8):
            for k,j in enumerate(y[i][4:-2].split()):
                self.tasbutonlar[i][k].resim_id.source = taslar[j]
                self.tasbutonlar[i][k].tas = j

    def secimKontrol(self, secim):
        # 0 sa BEYAZ, 1 SE SIYAH, 2 ISE TANIMLANMAMIS
        # Burda yapilacak cok is var:
        # 1. Tas yanacak(dogruysa), seciliyiYak() ile. Secili string e eklenecek.
        # Dogruluk kontrolu string parse edilerek bakilacak(mecbur)
        # 2. Yanlissa yanmayacak, secili listeye eklenmeyecek,yanlisSecim cagirilacak.
        # 3. Ikinci tas da dogruysa dogruSecim() cagirilacak
        # ARA ADIM: self.ust.oyun.board.parse() ile hareket gecerli mi konrolu yapilacak. Gecersizse 
        # iptal edilecek.
        # 4. dogruSecim() oynar ve olumlu dondururse ust sinifla DIREK SUNUCUYA GONDERILECEK.
        # Ekleme: sadece sunucuya gonderilmesin, ID 1 arttırılsın ve burda da islensin.
        # 5. Sira kontrol edilecek, karsidaysa sag tarafta belirtilecek(bind kullanilsa iyi olur).
        # ilerki asamalar: Sah mat kontrolu.

        # SIRA KIMDE? Karsidaysa uyari ver devam etme.
        if self.ust.oyun.board.get_turn() != self.ust.parent.taraf:
            self.siraKarsida()
            return False

        if self.yanik == 0:
            # BURADA SIYAH BEYAZ OLMASINA GORE KENDI TASI MI?
            if self.kendiTasi(self.tahtaParse(secim)):
                self.hamleString += secim
                self.seciliyiYak(secim)
                self.yanik = 1
            else:
                self.yanlisSecim()
        elif self.yanik == 1:
            self.hamleString += (" " + secim)
            self.yananiSondur()
            try:
                # deneme amacli:
                hamle = self.ust.oyun.board.parse(self.hamleString) # Bu sadece kontrolu saglar
                self.dogruSecim(hamle)
                print self.hamleString
                self.ust.yolla(self.hamleString)
            except:
                self.yanlisSecim()
            # Sifirlamalari yap
            self.yanik = 0
            self.hamleString = ""
        print self.tahtaParse(secim) # Ilk secilen bizim tasimiz olmak zorunda.
        # ikinci secilende sorun yok.

    def yanlisSecim(self):
        print "Secim yanlis"

    def dogruSecim(self,hamle):
        # ekleme yapilacak: sunucuya veriyi gonder.
        self.ust.oyun.move(hamle)
        self.tahtaGuncelle()
        self.ust.sonID += 1

    def seciliyiYak(self, secim):
        # self.yananTas = self.tasbutonlar[int(secim[1])]["abcdefgh".index(secim[0])-1]
        self.yananTas = self.tasbutonlar[7-(int(secim[1])-1)]['abcdefgh'.index(secim[0])]
        self.eskiArkaRenk = self.yananTas.background_color
        self.yananTas.background_color = (0,0,0,1)
        print "yakildi.", secim

    def yananiSondur(self):
        self.yananTas.background_color = self.eskiArkaRenk 

    def siraKarsida(self):
        print "Sira karsinin"

    def tahtaParse(self, konum):
        '''
        a2, e3 seklindeki konumda hangi tasin oldugunu dondurur. R ya da p gibi sonuc verir.
        Belirtilen konumda tas yoksa "." dondurur.
        '''
        # print self.ust.oyun.board.parse("b1 a3")

        a = str(self.ust.oyun.board) # a degiskeninde sadece . ve tas isimleri olacak.
        a = a.split("\n")
        a = a[1:-2]
        a = [i[3:-2].split() for i in a]
        return a[7-(int(konum[1])-1)]['abcdefgh'.index(konum[0])]

    def kendiTasi(self,tas):
        if self.ust.parent.taraf == 0: # Beyaz seciliyse
            return tas.isupper()
        elif self.ust.parent.taraf == 1: # Siyah seciliyse
            return tas.islower()

class SiyahTaraf(FloatLayout):
    def __init__(self):
        FloatLayout.__init__(self)
        self.baglanti = baglanti.BaglantiYonet(self.aktifBaglanti,self.gelenVeri,self.kayipBaglanti)
        self.baglanti.baglantiKur()
        self.sonID = 0

    def aktifBaglanti(self):
        self.clear_widgets()
        self.add_widget(Label(text = "Baglanti aktif. Taslar yukleniyor..."))
        self.baglanti.mesajGonder(str(self.sonID))
        Clock.schedule_interval(self.guncelle, 3)

    def guncelle(self,dt):
        self.baglanti.mesajGonder(str(self.sonID))

    def gelenVeri(self, veri):
        '''
        Sunucudan alinan veriler burda yorumlanacak ve isleme dokulecek.
        '''
        if self.sonID == 0:
            self.clear_widgets()
            self.oyunKur()
            self.sonID += 1

        if veri == "ALINDI":
            print "Hamle sunucuya basariyla iletildi"
            return True

        for i in veri.split("\n"):
            if len(i)>5:
                i = i[:6]
            if len(i) == 5:
                self.oyun.move(self.oyun.board.parse(i))
                self.sonID += 1
                print "Oynanan: ", i
        self.oyunTahtasi.tahtaGuncelle() # DUZENLE

    def oyunKur(self):
        self.oyun = chess.Game()
        self.oyun.setup()            
        self.oyunTahtasi = Tahta(self)
        self.add_widget(self.oyunTahtasi)
        self.add_widget(YanMenu(self.parent))

    def yolla(self, mesaj):
        '''
        Sunucuya istenen mesajin gonderilmesi icin islev gorur.
        self.baglanti.mesajGonder() ile ayni islevdedir.
        '''
        self.baglanti.mesajGonder(mesaj)

    def kayipBaglanti(self, sebep):
        pass

class BeyazTaraf(FloatLayout):
    def __init__(self):
        FloatLayout.__init__(self)
        self.baglanti = baglanti.BaglantiYonet(self.aktifBaglanti,self.gelenVeri,self.kayipBaglanti)
        self.baglanti.baglantiKur()
        self.sonID = 0

    def aktifBaglanti(self):
        self.clear_widgets()
        self.add_widget(Label(text = "Baglanti aktif. Taslar yukleniyor..."))
        self.baglanti.mesajGonder(str(self.sonID))
        Clock.schedule_interval(self.guncelle, 3)

    def guncelle(self,dt):
        self.baglanti.mesajGonder(str(self.sonID))

    def gelenVeri(self, veri):
        '''
        Sunucudan alinan veriler burda yorumlanacak ve isleme dokulecek.
        '''
        if self.sonID == 0:
            self.clear_widgets()
            self.oyunKur()
            self.sonID += 1

        if veri == "ALINDI":
            print "Hamle sunucuya basariyla iletildi"
            return True

        for i in veri.split("\n"):
            if len(i)>5:
                i = i[:6]
            if len(i) == 5:
                self.oyun.move(self.oyun.board.parse(i))
                self.sonID += 1
                print "Oynanan: ", i
        self.oyunTahtasi.tahtaGuncelle() # DUZENLE

    def oyunKur(self):
        self.oyun = chess.Game()
        self.oyun.setup()            
        self.oyunTahtasi = Tahta(self)
        self.add_widget(self.oyunTahtasi)
        self.add_widget(YanMenu(self.parent))

    def yolla(self, mesaj):
        '''
        Sunucuya istenen mesajin gonderilmesi icin islev gorur.
        self.baglanti.mesajGonder() ile ayni islevdedir.
        '''
        self.baglanti.mesajGonder(mesaj)

    def kayipBaglanti(self, sebep):
        pass

class Karsilama(GridLayout):
    def beyazSec(self):
        self.parent.taraf = 0
        self.parent.wEkle(BeyazTaraf)
        print "Beyaz taraf secildi."

    def siyahSec(self):
        self.parent.taraf = 1
        self.parent.wEkle(SiyahTaraf)
        print "Siyah taraf secildi."

class Uygulama(FloatLayout):
    def __init__(self):
        FloatLayout.__init__(self)
        self.taraf = -1
        self.menuBaslat()

    def menuBaslat(self):
        self.kmenu = Karsilama()
        self.add_widget(self.kmenu)

    def icerikTemizle(self):
        self.clear_widgets()

    def wEkle(self,snf):
        self.clear_widgets()
        self.tarafW = snf()
        self.add_widget(self.tarafW)

class AsgardApp(App):
    def build(self):
        self.uygulama = Uygulama()
        return self.uygulama

if __name__ == '__main__':
    AsgardApp().run()

Ve main.py’nin görünümüne yardımcı olan asgard.kv:

<Karsilama>:
    rows: 3
    cols: 1
    size_hint: 1.0, 1.0
    kyazi: ustyazi
    Label:
        id: ustyazi
        markup: True
        text: "[size=15][b]Oynanacak Tarafı Seçiniz[/b][/size]"
        pos_hint: {'x': 0.5 - (self.size_hint_x / 2), 'y': 0.5 - (self.size_hint_y / 2)}
    Button:
        id: b1
        text: "Beyaz"
        on_release: self.parent.beyazSec()
    Button:
        id: b2
        text: "Siyah"
        on_release: self.parent.siyahSec()

<SiyahTaraf>:
    size_hint: 1.0, 1.0
    Label:
        markup: True
        text: "[size=20][b]Sunucu Bağlantısı Kuruluyor...[/b][/size]"

<BeyazTaraf>:
    size_hint: 1.0, 1.0
    Label:
        markup: True
        text: "[size=20][b]Sunucu Bağlantısı Kuruluyor...[/b][/size]"

<YanMenu>:
    size_hint: 0.2, 1.0
    pos_hint: {'x': 0.8, 'y': 0}
    Label:
        row: 1
        text: "Taraf: %s" %self.parent.taraf

<Tahta>:
    rows: 8
    cols: 8

<Kutula>:
    resim_id: resim
    pos: self.pos
    size: self.size
    Image:
        id: resim
        size: root.size
        pos: root.pos

Chess.py dosyası da main.py’nin çalışabilmesi için haliyle gerekiyor. Onun çok uzun olmasından dolayı şu adresten düzenlediğim haline, şu adresten de orijinal haline ulaşabilirsiniz.

Herkese iyi çalışmalar.

 
comments powered by Disqus