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.
Öncelikle server side tarafı ile başlıyalım. Hareket tiplerimiz aşağıda görüldüğü gibi enum ile belirtilmiştir.
1 2 3 4 5 |
public enum MoveType { X=1, O=2 } |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public ActionResult Index() { //Get Cookie Player Name if (System.Web.HttpContext.Current.Request.Cookies["TicTacToeNick"]!=null && System.Web.HttpContext.Current.Request.Cookies["TicTacToeNick"]["TicTacToePlayer"] != null) { if (System.Web.HttpContext.Current.Cache["PlayerList"] != null) { string playerName = System.Web.HttpContext.Current.Request.Cookies["TicTacToeNick"]["TicTacToePlayer"]; string playerID = System.Web.HttpContext.Current.Request.Cookies["TicTacToeNick"]["TicTacToePlayerID"]; if (((List<string>)System.Web.HttpContext.Current.Cache["PlayerList"]).Count == 1 && playerName != ((List<string>)System.Web.HttpContext.Current.Cache["PlayerList"]).FirstOrDefault()) { HttpCookie myCookie = new HttpCookie("TicTacToeNick"); myCookie.Expires = DateTime.Now.AddDays(-1d); System.Web.HttpContext.Current.Response.Cookies.Add(myCookie); } else { ViewBag.PlayerCookie = playerName.ToUpper(); ViewBag.realPlayerCookie = playerName; ViewBag.PlayerID = playerID; } } else { HttpCookie myCookie = new HttpCookie("TicTacToeNick"); myCookie.Expires = DateTime.Now.AddDays(-1d); System.Web.HttpContext.Current.Response.Cookies.Add(myCookie); } } |
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.
1 2 3 4 5 6 7 |
public class Veri { public List<string> Xmoves { get; set; } public List<string> Omoves { get; set; } public int MoveType { get; set; } public List<string> Player { get; set; } } |
İsterseniz şimdi View’a gitmeden önce modelimizi cache’deki bilgilerden dolduralım.
1 2 3 4 5 6 7 8 9 10 |
Veri ver = new Veri(); ver.Xmoves = System.Web.HttpContext.Current.Cache["Xmoves"] as List<string>; ver.Omoves = System.Web.HttpContext.Current.Cache["Omoves"] as List<string>; if(System.Web.HttpContext.Current.Cache["MoveType"]!=null) ver.MoveType = (int)System.Web.HttpContext.Current.Cache["MoveType"]; if (System.Web.HttpContext.Current.Cache["PlayerList"] != null) ver.Player = (List<string>)System.Web.HttpContext.Current.Cache["PlayerList"]; else ver.Player = new List<string>(); return View(ver); |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
public static void recordCordinates(string cordinate,int moveType) { Veri ver = new Veri(); ver.Xmoves = System.Web.HttpContext.Current.Cache["Xmoves"] as List<string>; ver.Omoves = System.Web.HttpContext.Current.Cache["Omoves"] as List<string>; if (System.Web.HttpContext.Current.Cache["MoveType"] != null) ver.MoveType = (int)System.Web.HttpContext.Current.Cache["MoveType"]; if (moveType == (int)MoveType.X) { if (ver.Xmoves == null) { List<string> Xmoves = new List<string>(); Xmoves.Add(cordinate); System.Web.HttpContext.Current.Cache.Insert("Xmoves", Xmoves, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); System.Web.HttpContext.Current.Cache.Insert("MoveType", moveType, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); } else { ver.Xmoves.Add(cordinate); System.Web.HttpContext.Current.Cache["Xmoves"] = ver.Xmoves; System.Web.HttpContext.Current.Cache["MoveType"]= moveType; } } else if (moveType == (int)MoveType.O) { if (ver.Omoves == null) { List<string> Omoves = new List<string>(); Omoves.Add(cordinate); System.Web.HttpContext.Current.Cache.Insert("Omoves", Omoves, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); System.Web.HttpContext.Current.Cache.Insert("MoveType", moveType, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); } else { ver.Omoves.Add(cordinate); System.Web.HttpContext.Current.Cache["Omoves"] = ver.Omoves; System.Web.HttpContext.Current.Cache["MoveType"]= moveType; } } } |
Ş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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
static private List<int> Xmoves = new List<int>(); static private List<int> Omoves = new List<int>(); static private List<string> PlayerList = new List<string>(); public class TicTac : Hub { static private int[,] Cordinates = new int[,] { {0,1,2}, {3,4,5}, {6,7,8} }; static private int[,] Winners = new int[,] { {0,1,2}, {3,4,5}, {6,7,8}, {0,3,6}, {1,4,7}, {2,5,8}, {0,4,8}, {2,4,6} }; |
Ş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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
private int insertCordinate(string cordinate, int moveType, out bool doIT) { doIT = true; int index=cordinate.ToCharArray().ToList().FindIndex(c => c != '0'); int value = int.Parse(cordinate.ToCharArray().ToList().Where(c => c != '0').FirstOrDefault().ToString()) - 1; int cord = Cordinates[value, index]; if (moveType == (int)MoveType.X) { if (Xmoves.Contains(cord) == false && Omoves.Contains(cord) == false) { Xmoves.Add(cord); //System.Web.HttpContext.Current.Cache.Insert("Xmoves", Xmoves, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(1000)); recordCordinates(cordinate, moveType); for (int i = 0; i < 8; i++) { int a = Winners[i, 0], b = Winners[i, 1], c = Winners[i, 2]; if (Xmoves.Contains(a) && Xmoves.Contains(b) && Xmoves.Contains(c)) { Xmoves.Clear(); Omoves.Clear(); System.Web.HttpContext.Current.Cache.Remove("Omoves"); System.Web.HttpContext.Current.Cache.Remove("Xmoves"); System.Web.HttpContext.Current.Cache.Remove("MoveType"); return 1; } } } else { doIT = false; } } else if (moveType == (int)MoveType.O) { if (Xmoves.Contains(cord) == false && Omoves.Contains(cord) == false) { Omoves.Add(cord); //System.Web.HttpContext.Current.Cache.Insert("Omoves", Omoves, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(1000)); recordCordinates(cordinate, moveType); for (int i = 0; i < 8; i++) { int a = Winners[i, 0], b = Winners[i, 1], c = Winners[i, 2]; if (Omoves.Contains(a) && Omoves.Contains(b) && Omoves.Contains(c)) { Xmoves.Clear(); Omoves.Clear(); System.Web.HttpContext.Current.Cache.Remove("Omoves"); System.Web.HttpContext.Current.Cache.Remove("Xmoves"); System.Web.HttpContext.Current.Cache.Remove("MoveType"); return 1; } } } else { doIT = false; } } return 0; } |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public void checkMove(string cordinates, int moveType) { bool doIT; int winner=insertCordinate(cordinates,moveType,out doIT); if ((Xmoves.Count + Omoves.Count) == 9 || (Xmoves.Count + Omoves.Count) > 9) { winner = 2; Xmoves.Clear(); Omoves.Clear(); System.Web.HttpContext.Current.Cache.Remove("Omoves"); System.Web.HttpContext.Current.Cache.Remove("Xmoves"); System.Web.HttpContext.Current.Cache.Remove("MoveType"); } Clients.All.insertMove(cordinates,winner,doIT,moveType); } |
Ş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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
public bool saveCookie(string player, int playerID) { try { if(!PlayerList.Contains(player+"æ"+playerID.ToString())) { PlayerList.Add(player + "æ" + playerID.ToString()); } System.Web.HttpContext.Current.Cache.Insert("PlayerList", PlayerList, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); HttpCookie myCookie = new HttpCookie("TicTacToeNick"); myCookie["TicTacToePlayer"] = player; myCookie["TicTacToePlayerID"] = playerID.ToString(); myCookie.Expires = DateTime.Now.AddMinutes(50); System.Web.HttpContext.Current.Response.Cookies.Add(myCookie); System.Web.HttpContext.Current.Cache.Insert("Player" + playerID.ToString(), player, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); System.Web.HttpContext.Current.Cache.Insert("PlayerID", playerID.ToString(), null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); Clients.All.setNick(playerID, player); return true; } catch (Exception ex) { return false; } } public bool delCookie(int playerID) { try { if (System.Web.HttpContext.Current.Request.Cookies["TicTacToeNick"] != null) { HttpCookie myCookie = new HttpCookie("TicTacToeNick"); myCookie.Expires = DateTime.Now.AddDays(-1d); System.Web.HttpContext.Current.Response.Cookies.Add(myCookie); } System.Web.HttpContext.Current.Cache.Remove("Player" + playerID.ToString()); System.Web.HttpContext.Current.Cache.Remove("Omoves"); System.Web.HttpContext.Current.Cache.Remove("Xmoves"); System.Web.HttpContext.Current.Cache.Remove("MoveType"); if (System.Web.HttpContext.Current.Cache["PlayerID"] != null) { string pID = System.Web.HttpContext.Current.Cache["PlayerID"].ToString(); System.Web.HttpContext.Current.Cache.Remove("PlayerID"); System.Web.HttpContext.Current.Cache.Remove("Player" + pID); } else { System.Web.HttpContext.Current.Cache.Remove("Player" + playerID); } Xmoves.Clear(); Omoves.Clear(); PlayerList.Clear(); Clients.All.delNick(playerID); return true; } catch (Exception ex) { return false; } } |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
public bool clearMem() { try { System.Web.HttpContext.Current.Cache.Remove("Omoves"); System.Web.HttpContext.Current.Cache.Remove("Xmoves"); System.Web.HttpContext.Current.Cache.Remove("MoveType"); System.Web.HttpContext.Current.Cache.Remove("PlayerID"); System.Web.HttpContext.Current.Cache.Remove("Player1"); System.Web.HttpContext.Current.Cache.Remove("Player2"); Xmoves.Clear(); Omoves.Clear(); PlayerList.Clear(); Clients.All.clearCookie(); return true; } catch (Exception ex) { return false; } } public bool delAllCookie() { try { if (System.Web.HttpContext.Current.Request.Cookies["TicTacToeNick"] != null) { HttpCookie myCookie = new HttpCookie("TicTacToeNick"); myCookie.Expires = DateTime.Now.AddDays(-1d); System.Web.HttpContext.Current.Response.Cookies.Add(myCookie); } Clients.All.clearPage(); return true; } catch (Exception ex) { return false; } } //Disconnected....Olunca public override System.Threading.Tasks.Task OnDisconnected() { return base.OnDisconnected(); } |
Ş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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@model TicTacToe.Controllers.Veri @{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } <script type="text/javascript"> var messagehub = $.connection.ticTac; $(document).ready(function () { $(document).bind('keydown', function (event) { if (event.ctrlKey && event.altKey && event.shiftKey && event.which == 68) if ($('#tdClear').is(':hidden') == true) { $("#tdClear").show(); } else { $("#tdClear").hide(); } }); |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
$('#hdnPlayerID').val('@ViewBag.PlayerID') $('#hdnPlayerEnter').val('@ViewBag.PlayerID') if ($('#hdnPlayerID').val().trim() != "") { if ($('#hdnPlayerID').val().trim() == 1) { $("#txt1").hide(); $("#btnPlayer1").val("Oyundan Çık"); $("#btnPlayer2").hide(); $("#td2").hide(); $("#Name1").html('Player 1 ==> [@ViewBag.PlayerCookie]'); @if (Model.Player.Count > 1) { string secondName = ""; if (Model.Player.ElementAt(0).Split('æ')[0] == ViewBag.realPlayerCookie) { secondName = Model.Player.ElementAt(1).Split('æ')[0]; } else { secondName = Model.Player.ElementAt(0).Split('æ')[0]; } <text> $("#td2").show(); $("#txt2").hide(); $("#btnPlayer2").val("Oyundan Çık"); $("#td1").show(); $("#Name2").html('Player 2 ==> [@secondName]'); </text> } } else if ($('#hdnPlayerID').val().trim() == 2) { $("#txt2").hide(); $("#btnPlayer2").val("Oyundan Çık"); $("#btnPlayer1").hide(); $("#td1").hide(); $("#Name2").html('Player 2 ==> [@ViewBag.PlayerCookie]'); @if (Model.Player.Count > 1) { string secondName = ""; if (Model.Player.ElementAt(0).Split('æ')[0] == ViewBag.realPlayerCookie) { secondName = Model.Player.ElementAt(1).Split('æ')[0]; } else { secondName = Model.Player.ElementAt(0).Split('æ')[0]; } <text> $("#td1").show(); $("#txt1").hide(); $("#btnPlayer1").val("Oyundan Çık"); $("#td2").show(); $("#Name1").html('Player 1 ==> [@secondName]'); </text> } } } else { @if (Model.Player.Count > 1) { <text> $("#txt1").hide(); $("#btnPlayer1").hide(); $("#Name1").html('Player 1 ==> [@Model.Player.ElementAt(0).Split('æ')[0]]'); $("#txt2").hide(); $("#btnPlayer2").hide(); $("#Name2").html('Player 2 ==> [@Model.Player.ElementAt(1).Split('æ')[0]]'); </text> } else if (Model.Player.Count > 0) { if (Model.Player != null && Model.Player.FirstOrDefault().ToString().Split('æ')[1] == "1") { <text> $("#txt1").hide(); $("#btnPlayer1").hide(); $("#Name1").html('Player 1 ==> [@Model.Player.FirstOrDefault().ToString().Split('æ')[0]]'); </text> } else if (Model.Player != null && Model.Player.FirstOrDefault().ToString().Split('æ')[1] == "2") { <text> $("#txt2").hide(); $("#btnPlayer2").hide(); $("#Name2").html('Player 2 ==> [@Model.Player.FirstOrDefault().ToString().Split('æ')[0]]'); </text> } } } |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
$("#btnPlayer1").click(function () { if ($(this).val() == "Oyuna Gir") { var player1 = $("#txt1").val().trim(); $("#hdnPlayerEnter").val('1') messagehub.server.saveCookie(player1, 1); } else if ($(this).val() == "Oyundan Çık") { if ($('#txt2').is(':hidden') == false) { $("#btnPlayer2").val("Oyuna Gir"); $("#btnPlayer2").show(); } messagehub.server.delCookie(1); } }); $("#btnPlayer2").click(function () { if ($(this).val() == "Oyuna Gir") { //setNick(2); var player2 = $("#txt2").val().trim(); $("#hdnPlayerEnter").val('2') messagehub.server.saveCookie(player2, 2); } else if ($(this).val() == "Oyundan Çık") { //delNick(2); if ($('#txt1').is(':hidden') == false) { $("#btnPlayer1").val("Oyuna Gir"); $("#btnPlayer1").show(); } messagehub.server.delCookie(2); } }); $("#btnClear").click(function () { messagehub.server.clearMem(); }); |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
messagehub.client.clearCookie = function () { messagehub.server.delAllCookie(); } messagehub.client.clearPage = function () { $("#td1").show(); $("#td2").show(); $('#txt1').show(); $('#txt2').show(); $('#txt1').val(''); $('#txt2').val(''); $("#btnPlayer1").val("Oyuna Gir"); $("#btnPlayer1").show(); $("#btnPlayer2").val("Oyuna Gir"); $("#btnPlayer2").show(); $("#Name1").html('Player 1'); $("#Name2").html('Player 2'); $("hdnIP").val(''); $("hdnPlayerID").val(''); $("hdnPlayerEnter").val(''); $("#tdClear").hide(); } |
Ş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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$('#txt1').focus(); @if (Model.Xmoves != null) { foreach (string mov in Model.Xmoves) { @: var id = "img" + "@mov"; @: $("#" + id).attr("src", "/content/x.gif"); } } @if (Model.Omoves != null) { foreach (string mov2 in Model.Omoves) { @: var id = "img" + "@mov2"; @: $("#" + id).attr("src", "/content/o.gif"); } } @if (Model.MoveType != 0) { @:$('#hdnIP').val('@Model.MoveType'); } |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
$('a').each(function () { $(this).click(function () { if ($("#hdnPlayerEnter").val().trim() != "") { var moveType; if ($("#hdnIP").val() == "") { moveType = "1"; } else { moveType = $('#hdnIP').val() == "1" ? "2" : "1"; } if (moveType == $("#hdnPlayerEnter").val()) { var type = $('#hdnIP').val() == "1" ? "2" : "1"; messagehub.server.checkMove($(this).attr('id'), type); } } return false; }) }); messagehub.client.insertMove = function (idA, result, doIT, moveType) { if (doIT) { $('#hdnIP').val(moveType); var id = 'img' + idA if ($('#hdnIP').val() == '1') { $('#' + id).attr('src', '/content/x.gif'); } else if ($('#hdnIP').val() == '2') { $('#' + id).attr('src', '/content/o.gif'); } if (result == 1) { alert("Kazanan :" + $('#hdnIP').val() + ".Oyuncu"); $('img[id^="img"]').each(function () { $(this).attr('src', '/content/b.gif'); }); $('#hdnIP').val(''); } if (result == 2) { alert("Berabere Kaldınız"); $('img[id^="img"]').each(function () { $(this).attr('src', '/content/b.gif'); }); $('#hdnIP').val(''); } } } |
Ş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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
messagehub.client.setNick = function (playerID, name) { $('#hdnPlayerID').val(playerID); var doIT = $("#hdnPlayerEnter").val(); if (playerID == 1 && name != "") { $("#txt1").hide(); $("#btnPlayer1").val("Oyundan Çık"); if (doIT != "" && $('#txt2').is(':hidden') == false) { $("#btnPlayer2").hide(); $("#td2").hide(); } else if (doIT == "") { $("#btnPlayer1").hide(); } if (doIT != "" && $('#txt1').is(':hidden') == true) { $("#td1").show(); } $("#Name1").html('Player 1 ==> [' + name.toUpperCase() + ']'); } else if (playerID == 2 && name != "") { $("#txt2").hide(); $("#btnPlayer2").val("Oyundan Çık"); if (doIT != "" && $('#txt1').is(':hidden') == false) { $("#btnPlayer1").hide(); $("#td1").hide(); } else if (doIT == "") { $("#btnPlayer2").hide(); } if (doIT != "" && $('#txt2').is(':hidden') == true) { $("#td2").show(); } $("#Name2").html('Player 2 ==> [' + name.toUpperCase() + ']'); } } messagehub.client.delNick = function (playerID) { $('#hdnPlayerID').val(''); $('#hdnPlayerEnter').val(''); if (playerID == 1) { $("#txt1").show(); $("#txt1").val(''); if ($("#btnPlayer2").is(':hidden') == true || $("#btnPlayer2").is(':hidden') == false && $("#btnPlayer2").val() == 'Oyuna Gir') { $("#btnPlayer1").show(); } $("#btnPlayer1").val("Oyuna Gir"); $("#td2").show(); $("#Name1").html('Player 1'); $('img[id^="img"]').each(function () { $(this).attr('src', '/content/b.gif'); }); $('#hdnIP').val(''); $('#hdnPlayerEnter').val(''); if ($('#txt2').is(':hidden') == false) { $("#btnPlayer1").val("Oyuna Gir"); $("#btnPlayer1").show(); } } else if (playerID == 2) { $("#txt2").show(); $("#txt2").val(''); if ($("#btnPlayer1").is(':hidden') == true || $("#btnPlayer1").is(':hidden') == false && $("#btnPlayer1").val() == 'Oyuna Gir') { $("#btnPlayer2").show(); } $("#btnPlayer2").val("Oyuna Gir"); $("#td1").show(); $("#Name2").html('Player 2'); $('img[id^="img"]').each(function () { $(this).attr('src', '/content/b.gif'); }); $('#hdnIP').val(''); $('#hdnPlayerEnter').val(''); if ($('#txt1').is(':hidden') == false) { $("#btnPlayer2").val("Oyuna Gir"); $("#btnPlayer2").show(); } } } $.connection.hub.start(); |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
<div> <img src="/content/me.jpg" style="width: 50px" /> <b><font color="red" size="5em"> Tic </font>- <font color="yellow" size="5em"> Tac </font>- <font color="blue" size="5em">Toe</font></b></font> </div> <table> <tr> <td id="td1"><b id="Name1">Player 1</b> <img src="/content/x.gif" border="0" width="30" height="30"><input type="text" id="txt1" /></td> <td> <input type="button" id="btnPlayer1" style="color: orange" value="Oyuna Gir" /></td> <td id="td2"><b id="Name2">Player 2</b> <img src="/content/o.gif" border="0" width="30" height="30"><input type="text" id="txt2" /></td> <td> <input type="button" id="btnPlayer2" style="color: orange" value="Oyuna Gir" /></td> <td style="display:none" id="tdClear"> <input type="button" id="btnClear" style="color: orange" value="CacheTemizle" /> </td> </tr> <hr /> </table> <hr /> <br /> @Html.Hidden("hdnIP") @Html.Hidden("hdnPlayerID") @Html.Hidden("hdnPlayerEnter") <body> <a id="100" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img100"></a> <img src="/content/v.gif" width="13" height="40"> <a id="010" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img010"></a> <img src="/content/v.gif" border="0" width="13" height="40"> <a id="001" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img001"></a> <br> <img src="/content/h.gif" width="172" height="12"><br> <a id="200" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img200"></a> <img src="/content/v.gif" width="13" height="40"> <a id="020" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img020"></a> <img src="/content/v.gif" width="13" height="40"> <a id="002" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img002"></a> <br> <img src="/content/h.gif" width="172" height="12"><br> <a id="300" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img300"></a> <img src="/content/v.gif" width="13" height="40"> <a id="030" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img030"></a> <img src="/content/v.gif" width="13" height="40"> <a id="003" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img003"></a> </body> |
Index.cshtml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
@model TicTacToe.Controllers.Veri @{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } <script type="text/javascript"> var messagehub = $.connection.ticTac; $(document).ready(function () { $(document).bind('keydown', function (event) { if (event.ctrlKey && event.altKey && event.shiftKey && event.which == 68) if ($('#tdClear').is(':hidden') == true) { $("#tdClear").show(); } else { $("#tdClear").hide(); } }); $('#hdnPlayerID').val('@ViewBag.PlayerID') $('#hdnPlayerEnter').val('@ViewBag.PlayerID') if ($('#hdnPlayerID').val().trim() != "") { if ($('#hdnPlayerID').val().trim() == 1) { $("#txt1").hide(); $("#btnPlayer1").val("Oyundan Çık"); $("#btnPlayer2").hide(); $("#td2").hide(); $("#Name1").html('Player 1 ==> [@ViewBag.PlayerCookie]'); @if (Model.Player.Count > 1) { string secondName = ""; if (Model.Player.ElementAt(0).Split('æ')[0] == ViewBag.realPlayerCookie) { secondName = Model.Player.ElementAt(1).Split('æ')[0]; } else { secondName = Model.Player.ElementAt(0).Split('æ')[0]; } <text> $("#td2").show(); $("#txt2").hide(); $("#btnPlayer2").val("Oyundan Çık"); $("#td1").show(); $("#Name2").html('Player 2 ==> [@secondName]'); </text> } } else if ($('#hdnPlayerID').val().trim() == 2) { $("#txt2").hide(); $("#btnPlayer2").val("Oyundan Çık"); $("#btnPlayer1").hide(); $("#td1").hide(); $("#Name2").html('Player 2 ==> [@ViewBag.PlayerCookie]'); @if (Model.Player.Count > 1) { string secondName = ""; if (Model.Player.ElementAt(0).Split('æ')[0] == ViewBag.realPlayerCookie) { secondName = Model.Player.ElementAt(1).Split('æ')[0]; } else { secondName = Model.Player.ElementAt(0).Split('æ')[0]; } <text> $("#td1").show(); $("#txt1").hide(); $("#btnPlayer1").val("Oyundan Çık"); $("#td2").show(); $("#Name1").html('Player 1 ==> [@secondName]'); </text> } } } else { @if (Model.Player.Count > 1) { <text> $("#txt1").hide(); $("#btnPlayer1").hide(); $("#Name1").html('Player 1 ==> [@Model.Player.ElementAt(0).Split('æ')[0]]'); $("#txt2").hide(); $("#btnPlayer2").hide(); $("#Name2").html('Player 2 ==> [@Model.Player.ElementAt(1).Split('æ')[0]]'); </text> } else if (Model.Player.Count > 0) { if (Model.Player != null && Model.Player.FirstOrDefault().ToString().Split('æ')[1] == "1") { <text> $("#txt1").hide(); $("#btnPlayer1").hide(); $("#Name1").html('Player 1 ==> [@Model.Player.FirstOrDefault().ToString().Split('æ')[0]]'); </text> } else if (Model.Player != null && Model.Player.FirstOrDefault().ToString().Split('æ')[1] == "2") { <text> $("#txt2").hide(); $("#btnPlayer2").hide(); $("#Name2").html('Player 2 ==> [@Model.Player.FirstOrDefault().ToString().Split('æ')[0]]'); </text> } } } $("#btnPlayer1").click(function () { if ($(this).val() == "Oyuna Gir") { var player1 = $("#txt1").val().trim(); $("#hdnPlayerEnter").val('1') messagehub.server.saveCookie(player1, 1); } else if ($(this).val() == "Oyundan Çık") { if ($('#txt2').is(':hidden') == false) { $("#btnPlayer2").val("Oyuna Gir"); $("#btnPlayer2").show(); } messagehub.server.delCookie(1); } }); $("#btnPlayer2").click(function () { if ($(this).val() == "Oyuna Gir") { var player2 = $("#txt2").val().trim(); $("#hdnPlayerEnter").val('2') messagehub.server.saveCookie(player2, 2); } else if ($(this).val() == "Oyundan Çık") { if ($('#txt1').is(':hidden') == false) { $("#btnPlayer1").val("Oyuna Gir"); $("#btnPlayer1").show(); } messagehub.server.delCookie(2); } }); $("#btnClear").click(function () { messagehub.server.clearMem(); }); messagehub.client.clearCookie = function () { messagehub.server.delAllCookie(); } messagehub.client.clearPage = function () { $("#td1").show(); $("#td2").show(); $('#txt1').show(); $('#txt2').show(); $('#txt1').val(''); $('#txt2').val(''); $("#btnPlayer1").val("Oyuna Gir"); $("#btnPlayer1").show(); $("#btnPlayer2").val("Oyuna Gir"); $("#btnPlayer2").show(); $("#Name1").html('Player 1'); $("#Name2").html('Player 2'); $("hdnIP").val(''); $("hdnPlayerID").val(''); $("hdnPlayerEnter").val(''); $("#tdClear").hide(); } $('#txt1').focus(); @if (Model.Xmoves != null) { foreach (string mov in Model.Xmoves) { @: var id = "img" + "@mov"; @: $("#" + id).attr("src", "/content/x.gif"); } } @if (Model.Omoves != null) { foreach (string mov2 in Model.Omoves) { @: var id = "img" + "@mov2"; @: $("#" + id).attr("src", "/content/o.gif"); } } @if (Model.MoveType != 0) { @:$('#hdnIP').val('@Model.MoveType'); } $('a').each(function () { $(this).click(function () { if ($("#hdnPlayerEnter").val().trim() != "") { var moveType; if ($("#hdnIP").val() == "") { moveType = "1"; } else { moveType = $('#hdnIP').val() == "1" ? "2" : "1"; } if (moveType == $("#hdnPlayerEnter").val()) { var type = $('#hdnIP').val() == "1" ? "2" : "1"; messagehub.server.checkMove($(this).attr('id'), type); } } return false; }) }); }); messagehub.client.insertMove = function (idA, result, doIT, moveType) { if (doIT) { $('#hdnIP').val(moveType); var id = 'img' + idA if ($('#hdnIP').val() == '1') { $('#' + id).attr('src', '/content/x.gif'); } else if ($('#hdnIP').val() == '2') { $('#' + id).attr('src', '/content/o.gif'); } if (result == 1) { alert("Kazanan :" + $('#hdnIP').val() + ".Oyuncu"); $('img[id^="img"]').each(function () { $(this).attr('src', '/content/b.gif'); }); $('#hdnIP').val(''); } if (result == 2) { alert("Berabere Kaldınız"); $('img[id^="img"]').each(function () { $(this).attr('src', '/content/b.gif'); }); $('#hdnIP').val(''); } } } messagehub.client.setNick = function (playerID, name) { $('#hdnPlayerID').val(playerID); var doIT = $("#hdnPlayerEnter").val(); if (playerID == 1 && name != "") { $("#txt1").hide(); $("#btnPlayer1").val("Oyundan Çık"); if (doIT != "" && $('#txt2').is(':hidden') == false) { $("#btnPlayer2").hide(); $("#td2").hide(); } else if (doIT == "") { $("#btnPlayer1").hide(); } if (doIT != "" && $('#txt1').is(':hidden') == true) { $("#td1").show(); } $("#Name1").html('Player 1 ==> [' + name.toUpperCase() + ']'); } else if (playerID == 2 && name != "") { $("#txt2").hide(); $("#btnPlayer2").val("Oyundan Çık"); if (doIT != "" && $('#txt1').is(':hidden') == false) { $("#btnPlayer1").hide(); $("#td1").hide(); } else if (doIT == "") { $("#btnPlayer2").hide(); } if (doIT != "" && $('#txt2').is(':hidden') == true) { $("#td2").show(); } $("#Name2").html('Player 2 ==> [' + name.toUpperCase() + ']'); } } messagehub.client.delNick = function (playerID) { $('#hdnPlayerID').val(''); $('#hdnPlayerEnter').val(''); if (playerID == 1) { $("#txt1").show(); $("#txt1").val(''); if ($("#btnPlayer2").is(':hidden') == true || $("#btnPlayer2").is(':hidden') == false && $("#btnPlayer2").val() == 'Oyuna Gir') { $("#btnPlayer1").show(); } $("#btnPlayer1").val("Oyuna Gir"); //$("#btnPlayer2").show(); $("#td2").show(); $("#Name1").html('Player 1'); $('img[id^="img"]').each(function () { $(this).attr('src', '/content/b.gif'); }); $('#hdnIP').val(''); $('#hdnPlayerEnter').val(''); if ($('#txt2').is(':hidden') == false) { $("#btnPlayer1").val("Oyuna Gir"); $("#btnPlayer1").show(); } } else if (playerID == 2) { $("#txt2").show(); $("#txt2").val(''); if ($("#btnPlayer1").is(':hidden') == true || $("#btnPlayer1").is(':hidden') == false && $("#btnPlayer1").val() == 'Oyuna Gir') { $("#btnPlayer2").show(); } $("#btnPlayer2").val("Oyuna Gir"); //$("#btnPlayer1").show(); $("#td1").show(); $("#Name2").html('Player 2'); $('img[id^="img"]').each(function () { $(this).attr('src', '/content/b.gif'); }); $('#hdnIP').val(''); $('#hdnPlayerEnter').val(''); if ($('#txt1').is(':hidden') == false) { $("#btnPlayer2").val("Oyuna Gir"); $("#btnPlayer2").show(); } } } $.connection.hub.start(); </script> <div> <img src="/content/me.jpg" style="width: 50px" /> <b><font color="red" size="5em"> Tic </font>- <font color="yellow" size="5em"> Tac </font>- <font color="blue" size="5em">Toe</font></b></font> </div> <table> <tr> <td id="td1"><b id="Name1">Player 1</b> <img src="/content/x.gif" border="0" width="30" height="30"><input type="text" id="txt1" /></td> <td> <input type="button" id="btnPlayer1" style="color: orange" value="Oyuna Gir" /></td> <td id="td2"><b id="Name2">Player 2</b> <img src="/content/o.gif" border="0" width="30" height="30"><input type="text" id="txt2" /></td> <td> <input type="button" id="btnPlayer2" style="color: orange" value="Oyuna Gir" /></td> <td style="display:none" id="tdClear"> <input type="button" id="btnClear" style="color: orange" value="CacheTemizle" /> </td> </tr> <hr /> </table> <hr /> <br /> @Html.Hidden("hdnIP") @Html.Hidden("hdnPlayerID") @Html.Hidden("hdnPlayerEnter") @*@Request.UserHostAddress*@ <body> <a id="100" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img100"></a> <img src="/content/v.gif" width="13" height="40"> <a id="010" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img010"></a> <img src="/content/v.gif" border="0" width="13" height="40"> <a id="001" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img001"></a> <br> <img src="/content/h.gif" width="172" height="12"><br> <a id="200" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img200"></a> <img src="/content/v.gif" width="13" height="40"> <a id="020" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img020"></a> <img src="/content/v.gif" width="13" height="40"> <a id="002" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img002"></a> <br> <img src="/content/h.gif" width="172" height="12"><br> <a id="300" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img300"></a> <img src="/content/v.gif" width="13" height="40"> <a id="030" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img030"></a> <img src="/content/v.gif" width="13" height="40"> <a id="003" href=""> <img src="/content/b.gif" border="0" width="40" height="40" id="img003"></a> </body> |
HomeController.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 |
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Microsoft.AspNet.SignalR; namespace TicTacToe.Controllers { public enum MoveType { X=1, O=2 } public class Veri { public List<string> Xmoves { get; set; } public List<string> Omoves { get; set; } public int MoveType { get; set; } public List<string> Player { get; set; } } public class HomeController : Controller { // // GET: /Home/ public ActionResult Index() { //Get Cookie Player Name if (System.Web.HttpContext.Current.Request.Cookies["TicTacToeNick"]!=null && System.Web.HttpContext.Current.Request.Cookies["TicTacToeNick"]["TicTacToePlayer"] != null) { if (System.Web.HttpContext.Current.Cache["PlayerList"] != null) { string playerName = System.Web.HttpContext.Current.Request.Cookies["TicTacToeNick"]["TicTacToePlayer"]; string playerID = System.Web.HttpContext.Current.Request.Cookies["TicTacToeNick"]["TicTacToePlayerID"]; if (((List<string>)System.Web.HttpContext.Current.Cache["PlayerList"]).Count == 1 && playerName != ((List<string>)System.Web.HttpContext.Current.Cache["PlayerList"]).FirstOrDefault()) { HttpCookie myCookie = new HttpCookie("TicTacToeNick"); myCookie.Expires = DateTime.Now.AddDays(-1d); System.Web.HttpContext.Current.Response.Cookies.Add(myCookie); } else { ViewBag.PlayerCookie = playerName.ToUpper(); ViewBag.realPlayerCookie = playerName; ViewBag.PlayerID = playerID; } } else { HttpCookie myCookie = new HttpCookie("TicTacToeNick"); myCookie.Expires = DateTime.Now.AddDays(-1d); System.Web.HttpContext.Current.Response.Cookies.Add(myCookie); } } Veri ver = new Veri(); ver.Xmoves = System.Web.HttpContext.Current.Cache["Xmoves"] as List<string>; ver.Omoves = System.Web.HttpContext.Current.Cache["Omoves"] as List<string>; if(System.Web.HttpContext.Current.Cache["MoveType"]!=null) ver.MoveType = (int)System.Web.HttpContext.Current.Cache["MoveType"]; if (System.Web.HttpContext.Current.Cache["PlayerList"] != null) ver.Player = (List<string>)System.Web.HttpContext.Current.Cache["PlayerList"]; else ver.Player = new List<string>(); return View(ver); } public static void recordCordinates(string cordinate,int moveType) { Veri ver = new Veri(); ver.Xmoves = System.Web.HttpContext.Current.Cache["Xmoves"] as List<string>; ver.Omoves = System.Web.HttpContext.Current.Cache["Omoves"] as List<string>; if (System.Web.HttpContext.Current.Cache["MoveType"] != null) ver.MoveType = (int)System.Web.HttpContext.Current.Cache["MoveType"]; if (moveType == (int)MoveType.X) { if (ver.Xmoves == null) { List<string> Xmoves = new List<string>(); Xmoves.Add(cordinate); System.Web.HttpContext.Current.Cache.Insert("Xmoves", Xmoves, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); System.Web.HttpContext.Current.Cache.Insert("MoveType", moveType, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); } else { ver.Xmoves.Add(cordinate); System.Web.HttpContext.Current.Cache["Xmoves"] = ver.Xmoves; System.Web.HttpContext.Current.Cache["MoveType"]= moveType; } } else if (moveType == (int)MoveType.O) { if (ver.Omoves == null) { List<string> Omoves = new List<string>(); Omoves.Add(cordinate); System.Web.HttpContext.Current.Cache.Insert("Omoves", Omoves, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); System.Web.HttpContext.Current.Cache.Insert("MoveType", moveType, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); } else { ver.Omoves.Add(cordinate); System.Web.HttpContext.Current.Cache["Omoves"] = ver.Omoves; System.Web.HttpContext.Current.Cache["MoveType"]= moveType; } } } static private List<int> Xmoves = new List<int>(); static private List<int> Omoves = new List<int>(); static private List<string> PlayerList = new List<string>(); public class TicTac : Hub { static private int[,] Cordinates = new int[,] { {0,1,2}, {3,4,5}, {6,7,8} }; static private int[,] Winners = new int[,] { {0,1,2}, {3,4,5}, {6,7,8}, {0,3,6}, {1,4,7}, {2,5,8}, {0,4,8}, {2,4,6} }; private int insertCordinate(string cordinate, int moveType, out bool doIT) { doIT = true; int index=cordinate.ToCharArray().ToList().FindIndex(c => c != '0'); int value = int.Parse(cordinate.ToCharArray().ToList().Where(c => c != '0').FirstOrDefault().ToString()) - 1; int cord = Cordinates[value, index]; if (moveType == (int)MoveType.X) { if (Xmoves.Contains(cord) == false && Omoves.Contains(cord) == false) { Xmoves.Add(cord); //System.Web.HttpContext.Current.Cache.Insert("Xmoves", Xmoves, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(1000)); recordCordinates(cordinate, moveType); for (int i = 0; i < 8; i++) { int a = Winners[i, 0], b = Winners[i, 1], c = Winners[i, 2]; if (Xmoves.Contains(a) && Xmoves.Contains(b) && Xmoves.Contains(c)) { Xmoves.Clear(); Omoves.Clear(); System.Web.HttpContext.Current.Cache.Remove("Omoves"); System.Web.HttpContext.Current.Cache.Remove("Xmoves"); System.Web.HttpContext.Current.Cache.Remove("MoveType"); return 1; } } } else { doIT = false; } } else if (moveType == (int)MoveType.O) { if (Xmoves.Contains(cord) == false && Omoves.Contains(cord) == false) { Omoves.Add(cord); recordCordinates(cordinate, moveType); for (int i = 0; i < 8; i++) { int a = Winners[i, 0], b = Winners[i, 1], c = Winners[i, 2]; if (Omoves.Contains(a) && Omoves.Contains(b) && Omoves.Contains(c)) { Xmoves.Clear(); Omoves.Clear(); System.Web.HttpContext.Current.Cache.Remove("Omoves"); System.Web.HttpContext.Current.Cache.Remove("Xmoves"); System.Web.HttpContext.Current.Cache.Remove("MoveType"); return 1; } } } else { doIT = false; } } return 0; } public void checkMove(string cordinates, int moveType) { bool doIT; int winner=insertCordinate(cordinates,moveType,out doIT); if ((Xmoves.Count + Omoves.Count) == 9 || (Xmoves.Count + Omoves.Count) > 9) { winner = 2; Xmoves.Clear(); Omoves.Clear(); System.Web.HttpContext.Current.Cache.Remove("Omoves"); System.Web.HttpContext.Current.Cache.Remove("Xmoves"); System.Web.HttpContext.Current.Cache.Remove("MoveType"); } Clients.All.insertMove(cordinates,winner,doIT,moveType); } public bool saveCookie(string player, int playerID) { try { if(!PlayerList.Contains(player+"æ"+playerID.ToString())) { PlayerList.Add(player + "æ" + playerID.ToString()); } System.Web.HttpContext.Current.Cache.Insert("PlayerList", PlayerList, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); HttpCookie myCookie = new HttpCookie("TicTacToeNick"); myCookie["TicTacToePlayer"] = player; myCookie["TicTacToePlayerID"] = playerID.ToString(); myCookie.Expires = DateTime.Now.AddMinutes(50); System.Web.HttpContext.Current.Response.Cookies.Add(myCookie); System.Web.HttpContext.Current.Cache.Insert("Player" + playerID.ToString(), player, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); System.Web.HttpContext.Current.Cache.Insert("PlayerID", playerID.ToString(), null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(50)); Clients.All.setNick(playerID, player); return true; } catch (Exception ex) { return false; } } public bool delCookie(int playerID) { try { if (System.Web.HttpContext.Current.Request.Cookies["TicTacToeNick"] != null) { HttpCookie myCookie = new HttpCookie("TicTacToeNick"); myCookie.Expires = DateTime.Now.AddDays(-1d); System.Web.HttpContext.Current.Response.Cookies.Add(myCookie); } System.Web.HttpContext.Current.Cache.Remove("Player" + playerID.ToString()); System.Web.HttpContext.Current.Cache.Remove("Omoves"); System.Web.HttpContext.Current.Cache.Remove("Xmoves"); System.Web.HttpContext.Current.Cache.Remove("MoveType"); if (System.Web.HttpContext.Current.Cache["PlayerID"] != null) { string pID = System.Web.HttpContext.Current.Cache["PlayerID"].ToString(); System.Web.HttpContext.Current.Cache.Remove("PlayerID"); System.Web.HttpContext.Current.Cache.Remove("Player" + pID); } else { System.Web.HttpContext.Current.Cache.Remove("Player" + playerID); } Xmoves.Clear(); Omoves.Clear(); PlayerList.Clear(); Clients.All.delNick(playerID); return true; } catch (Exception ex) { return false; } } public bool clearMem() { try { System.Web.HttpContext.Current.Cache.Remove("Omoves"); System.Web.HttpContext.Current.Cache.Remove("Xmoves"); System.Web.HttpContext.Current.Cache.Remove("MoveType"); System.Web.HttpContext.Current.Cache.Remove("PlayerID"); System.Web.HttpContext.Current.Cache.Remove("Player1"); System.Web.HttpContext.Current.Cache.Remove("Player2"); Xmoves.Clear(); Omoves.Clear(); PlayerList.Clear(); Clients.All.clearCookie(); return true; } catch (Exception ex) { return false; } } public bool delAllCookie() { try { if (System.Web.HttpContext.Current.Request.Cookies["TicTacToeNick"] != null) { HttpCookie myCookie = new HttpCookie("TicTacToeNick"); myCookie.Expires = DateTime.Now.AddDays(-1d); System.Web.HttpContext.Current.Response.Cookies.Add(myCookie); } Clients.All.clearPage(); return true; } catch (Exception ex) { return false; } } //Disconnected....Olunca public override System.Threading.Tasks.Task OnDisconnected() { return base.OnDisconnected(); } } } } |
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(İptal) : http://tictactoeplay.azurewebsites.net/
Source Code : http://www.borakasmer.com/projects/TicTacToe.rar
Son Yorumlar