Android İçin Online Satranç Oyunu
- May 8, 2013
Asgard 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.
– 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.