TicTacToe With SignalR

Selamlar;

Bugün üyelikli bir tictactoe oyunu yazıcağız. Bilmeyenler için oyunun tek bir kuralı var o da 2 taraftan birinin X veya O şekillerinin 3 tanesini yanyana veya çapraz olarak dizmeyi başarmasıdır. Mvc,  signalR ve jquery teknolojileri kullanılarak 2 kişinin oynayıp,  diğer oyuna giren kişilerin de izleyebileceği keyifli bir web uygulaması yazacağız.

tic                               ticwin

Öncelikle server side tarafı ile başlıyalım. Hareket tiplerimiz aşağıda görüldüğü gibi enum ile belirtilmiştir.

Aşağıda Index() action’ında oyuna giriş yapan player varmı diye bakılır. Var ise cookie’deki kayıtlı player bilgileri ile oyuna giren cache’deki player bilgileri karşılaştırılıp farklılık durumunda cookie temizlenip yeni player bilgileri bu temizlenen cookie’ye aktarılır.

Oyundaki güncel bilgilerin tutulduğu Veri adında bir class oluşturulur. Bu bilgiler Oyundaki X ve O taşlarının hareket history’si, oyuncu bilgileri ve hareket tiplerini barındırır. Bu Index view’a göndereceğimiz data model dir.

İsterseniz şimdi View’a gitmeden önce modelimizi cache’deki bilgilerden dolduralım.

Aşağıda oyun sırasında yapılan her hamlenin  ardından yukarıda tanımlanan veri modeline ilgili hamlenin kordinat ve tipini aşağıda görüldüğü gibi kaydedelim.

Şimdi signalR Hub TicTac class’ı altında 3×3 lük tahtada kordinatların sayısal karşılıklarını ve kazanan kordinat dizilimlerini aşağıdaki gibi belirleyelim.

Şimdi de aşağıda bir player hamle yaptığı zaman hamle yapılan taşın türüne göre kordinatların yukarıda tanımlanan recordCordinates() methodu’da kullanılarak cache’e atılması ve yapılan hamlenin ardından türüne yani X veya O olmasına göre kazanan kordinatların hepsinin tek tek yapılan hamlenin history’sinden bakılarak check edilip kazanılıp kazanılmadığını kontrol edelim.  Ayrıca önceden bu kordinata hamle yapılıp yapılmadığına bakalım. Kazanılmış ise 1 değil ise 0 döndürelim. Ayrıca hamlenin yapılıp yapılamıyacağını bildiren doIT parametresini döndürelim. Örnek vermek gerekirse önceden hamle yapılan yere birdaha hamle yapılamıyacağı için doIT değerine false atılması gerekir.

Esas signalR ile her hamleden sonra çağrılan server side method, aşağıdaki checkMove() methodudur. Parametre olarak yapılan hamlenin tipi ve taşın konan yerine göre kordinatı gönderilir. Yukarıda tanımladığımız insertCordinate() burada çağrılır. Yani yukarıda tanımladığımız tüm methodlar burada kullanılır. Kazanılıp kazanılmadığına ve ilgili yapılan hamle cache atıldıktan sonra toplam hareket sayısına bakılır. Kazanan olmamış ve toplam hareket sayısı olan 9 dolmuş ise winner’a 2 değeri atanarak berabere olduğu belirtilir. Aynı zamanda tüm clientlara cordinate kazanılıp kazanılmadığı hareket tipi ve hamlenin yapılıp yapılamıyacağını bildiren doIT parametresi insertMove() javascript function’ı call edilerek dödürülür.

Şimdi isterseniz yeni bir kullanıcı giriş yapınca nasıl set edildiğini ve var olan kullanıcı çıkınca ne işler yapıldığını inceleyelim. Aşağıda görüldüğü gibi bir PlayerList’imiz var. Connect olan player bu list’te yoksa ekelenir. Aynı zamanda 50 dakikalık timeout ile cache’e ve cookie’ye eklenir. Daha sonra da diğer tüm clientların bundan haberdar olması için tüm client side’daki setNick() function’ı ilgili playerID ve  player parametreleri ile tetiklenir. Player’ın çıkması durumunda da tüm bu işlemlerin tersi olur ve ilgili cache ve cookieler temizlenir. Ayrıca cache’deki kordinatlar yani X ve O nun hamle geçmişi, hareket tipleri ve player listesi temizlenir. Ayrıca tüm clientların bundan haberdar olup yeni bir client’ın login olma şansı verilmesi için tüm client’lardaki delNick() function’ı ilgili playerID gönderilerek tetiklenir.

Son olarak Ctrl+Alt+Shift+D tuşlarına basılınca cache ve cooki’leri temizleyen bir button çıkarılır. Tıklanınca  alttaki kodlar çalışır. Aşağıda görüldüğü gibi tüm cacheler ve cooki’ler silinmektedir.

Şimdi isterseniz biraz da user interface yani client side tarafı ile ilgili kodları yazalım. Aşağıda görüldüğü gibi view’ımız Veri modelimizi beklemektedir. Ayrıca messagehub nesnemize ticTac signalR hub classı atanır. Daha sonra da ctrl+alt+shift ve D tuşlarına basılınca cache’i temizleyen clearMem() methodunun çağrıldığı button’u visible hale getiren kodlar yazılır.

Aşağıda playerların görünümü ile ilgili kısm yazılmıştır. Öncelikle server side’da ViewPage’e player bilgileri atılmışmı yani giriş yapmış player var mı diye bakılır. Giriş yapılmış ise ilgili player bilgileri hidden fieldlara atılır. Daha sonra kaç player giriş yapmış diye bakılır. Giren oyuncuların textboxları kaldırılıp, ilgili tableları visible hale getirilip oyundan çık butonu gösterilir.

player

Aşağıda player için oyundan çık yada oyuna gir butonlarına basılınca çağrılacak server side’daki hub class’ının delCookie() ve saveCookie() methodları ve cache temizle buttonuna basılınca çağrılacak  clearMem() methodunun çağrıldığı script kodlar görülmektedir.

Aşağıda görüldüğü gibi server side’daki clearMem() methodu çağrılınca o da client sidedaki aşağıdaki clearCookie() functionını signalR sayesinde çağrır, burdan da server side’daki  delAllCookie() methodu çağrılır ve tüm clientlardaki cookieler temizlenir. Daha sonra tüm clientlardaki clearPage() function’ını signalR sayesinde tetiklenerek ekran ilk haline döner. Ve playerların textboxları temizlenerek visible hale getirilir, oyuna gir buttonları da visible hale getirilerek hidden fieldlar temizlenir. Oyundan çık buttonları gizlenir.

o          x    put

Şimdi de  oyuna ilk girildiğinde Veri modeli ile gelen kordinatların ekrandaki playground’a yerleştirilmesi ve enson hamleyi kimin yaptığı ile ilgili bilginin tutulduğu hidden kısma bakalım. Aşağıda görüldüğü gibi X ve O taşları için önceden yapılmış hamleler tek tek gezilerek ilgili cordinate ile aynı isimden türemiş ‘img+cordinate’ şeklindeki image ID’leri bulunarak ilgili taşın gif değeri atanmıştır. o.gif veye x.gif ayrıca hdnIP değerine en son hamlenin kimde olduğu belirtilmiştir.

Aşağıda hamle yapıldığı zaman yani a href’lerden biri tıklandığı zaman öncelikle tıklama sırasının hangi playerda olduğuna bakılıp, sıra eğer hamleyi yapan player’da ise yukarıda tanımladığımız server side’daki checkMove() methodu çağrılır. Eğer oyun kazanılmamış veya hareket alanı bitmemiş yada hamle yapılmak istenen alanda başka bir taş yok ise aşağıda görülen tüm clientlardaki insertMove() function’ı tetiklenir ve tıklanan alana ilgili taş konur. Yani yapılan hamle kordinatlara kaydedilirken ilgili kordinattaki image’e ilgili taşın gif’i yani yapılan hareketin tipine göre ya X.gif’i yada O.gif’i atanır. Hamle yapılabilecek ise doIT değişkenine true atanır. result 1 ise kazanan playerlardan biridir. 2 ise playground’da hamle yapıcak yer kalmamıştır ve kimse kazanamadığı için berabere kalınmıştır.

Şimdi de yeni player oyun girdiği ve çıktığı durumlarda neler olduğunu inceleyelim. Tüm clientlar için setNick() function’ı ilgili playerID ve name ile tetiklenince ilgili hidden alanlara bu değişkenler aktarılır. Giren player’a göre 1 veya 2. playerın textbox’ı ve oyuna gir buttonu gizlenir. Oyundan çık buttonu ve playerın ismi büyük harfler ile gösterilir. Bütün bu işlemler oyuna gir buttonuna basılnca player için yapılan işlemlerdi. Bir de oyundan çık buttonuna basılınca server side’dan çağrılan  delNick() function’ı yukarıda bahssettiğimz adımları geriye işleterek tüm işlemleri sıfırlar yani oyundan çıkan player’a bağlı olarak ilgili hidden fieldlar temizlenip, oyundan çık buttonu ve player ismi gizlenerek player idsi ile birlikte isminin yazılacağı texbox ve oyuna gir buttonları gösterilir.

winner

Son olarak aşağıda playerların ve ilgili playground’ın herbir kordinatına karşılık gelen uniq idleri ile olan html kodu gösterilmektedir. Herbir kordinata özel id konması, kazanılıp kaybedilme durumlarının belirlenen kordinatlara göre kontrol edilmesine olanak sağlarken ilgili taşların da doğru yere konmasına olanak vermektedir.

Index.cshtml:

HomeController.cs:

Yukarıdaki örnekten de anlaşılacağı gibi signalR ile yapılabilecek şeylerin sınırı yoktur. Burada kullanıcı etkileşimli yani oyuna giriş, çıkış ve izleme işlemleri ile bunları yapan  clientlar arasında nasıl bir role farkının olduğuna, belirlenen rulelar ile belli bir alanda hem oynuyan hem de izleyen clientlar arasında signalR ile nasıl bir iletişim kurulabileceğine ve oyun yazmanın az da olsa nekadar zevkli olduğuna deyinmeye çalıştık. Siz de isterseniz bu projeyi biraz daha ileriye götürüp bir yapay zekaya karşı nasıl oynanabileceğini tasarlıyabilirsiniz.

Bir sonraki makalede görüşmek üzere hoşçakalın.

Örnek Web  : http://tictactoeplay.azurewebsites.net/

Source Code : http://www.borakasmer.com/projects/TicTacToe.rar

Herkes Görsün:

Sevebilirsin...

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir