程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C#網絡版斗地主——地主權限的傳遞

C#網絡版斗地主——地主權限的傳遞

編輯:關於C#

本文是對C#網絡版斗地主的總結。

首先服務器使用一個隨機數來隨即選出默認地主。然後發送信息給選出來的玩家。玩家接收到信息後顯示兩個按鈕“叫地主”,“不叫”。如果選擇不叫,則把可以叫地主的權限發送給另外一個玩家,如果另外兩個玩家都不要的話,就執行Restart()方法重新發牌。

叫地主權限的傳遞順序如下圖所示:

具體實現方法:

服務器得到一個1-3的隨機數,1代表服務器是默認地主(默認地主就是隨機選擇的第一個有權限叫地主的玩家),2代表client1是默認地主,3代表client2是默認地主。只有服務器端能夠選擇地主,所以該方法在server類中

public void SendOrder(int Num)
{
 switch (Num)
 {
  case 1:
   DConsole.player1.areYouLandLord = true; //把叫地主權限給自己
   break;
  case 2:
   this.SendDataForClient("AreYouLandLord", 1); //傳遞叫地主權限給client1
   break;
  case 3:
   this.SendDataForClient("AreYouLandLord", 2); //傳遞叫地主權限給client2
   break;
 }
}

客戶端的循環接收數據程序會分析服務端發送過來的數據,在client類:

(代碼比較長,所以只貼出和地主權限傳遞有關的一部分)

public void AcceptServerData()
{
 NetworkStream Ns = client.GetStream();
 string str = "";
 while (true)
 {
  byte[] bytes = new byte[108];
  Ns.Read(bytes, 0, 108);
  str = Encoding.Default.GetString(bytes);
  (省略一部分)
  if (str.StartsWith("AreYouLandLord")) //如果服務器向客戶端發送該消息,則客戶端獲取叫地主權限
  {
   DConsole.player1.areYouLandLord = true; //timer控件檢測到該屬性值為true時顯示出叫地主和不叫按鈕
   continue;
  }
  if (str.StartsWith("LandLordPokers")) //獲取服務器發送給客戶端的地主的3張牌,收到這三張牌後地主權限的傳遞就結束了
  {
   PokerGroup pokers = new PokerGroup();
   str = str.Replace("LandLordPokers", "");
   byte[] bytePg = Encoding.Default.GetBytes(str);
   pokers.GetPokerGroup(bytePg);
   DConsole.LandLordPokers = pokers; //把接收到的地主牌保存起來
   DConsole.player1.SelectLandLordEnd(); //該方法在窗口中央顯示出地主牌,然後判斷自己是不是地主,如果是地主就將地主牌添加到自己的牌組.該方法的具體代碼請看下文
   continue;
  }
  if (str.StartsWith("ClientIsLandLord")) //另外一個客戶端是地主
  {
   DConsole.lblClient2Name.Text += "(地主)";
   DConsole.lblClient2Name.ForeColor = System.Drawing.Color.Red;
   DConsole.PaintClient(20);
   continue;
  }
  if (str.StartsWith("ServerIsLandLord")) //服務器是地主
  {
   DConsole.lblClient1Name.Text += "(地主)";
   DConsole.lblClient1Name.ForeColor = System.Drawing.Color.Red;
   DConsole.PaintServer(20);
   continue;
  }
  (後面省略)
 }
}

player1.areYouLandLord為true後,timer控件會檢測到,然後把叫地主和不叫按鈕顯示出來。

叫地主按鈕的click事件:

this.player1.isLandLord = true; //本地玩家為地主
this.player1.haveOrder = true; //獲得出牌權限,下篇文章講到出牌權限的傳遞
this.player1.isBiggest = true; //出的牌是否為最大的,主要用於當你出的牌其他兩家都不要時,你自己不能不要,只能出牌,下篇文章會講到的
this.player1.areYouLandLord = false; //設置該值為false
this.btnNeedLandLord.Visible = false;
this.btnNotLandLord.Visible = false; //隱藏叫地主和不叫按鈕

if (this.server != null) //當玩家為服務器時
{
 this.player1.SelectLandLordEnd(); //該方法在窗口中央顯示出地主牌,然後判斷自己是不是地主,如果是地主就將地主牌添加到自己的牌組.該方法的具體代碼請看下文
 this.server.SendDataForClient("LandLordPokers", DConsole.LandLordPokers, 1); //把地主的三張牌發送給client1,因為不管誰是地主,客戶端都需要獲得地主的牌並且顯示出來
 Thread.Sleep(100);
 this.server.SendDataForClient("LandLordPokers", DConsole.LandLordPokers, 2); //同上,把數據發送個client2
 Thread.Sleep(100);
 this.server.SendDataForClient("ServerIsLandLord", 1); //通知client1,服務器是地主
 Thread.Sleep(100);
 this.server.SendDataForClient("ServerIsLandLord", 2); //通知client2,服務器是地主
 Thread.Sleep(100);
}
if (this.client != null) //當玩家為客戶端時
{
 this.client.SendDataForServer("IamLandLord"); //發送信息給服務器,服務器可以識別是哪個客戶端叫了地主,服務器如何處理請看下文的server類代碼
 Thread.Sleep(300);
}

當玩家單擊“不叫”按鈕時。如果玩家是服務器,如第一張圖所示,程序會向他的下家發送選擇地主的權限,當LandLordNum為3時,服務器就是最後一個玩家,如果他也不叫地主的話,就只能重新發牌了。

如果玩家是客戶端的話,直接向server端發送"AreYouLandLord"來表明自己不要地主。

Server端會判斷是client1還是client2發送的消息,然後做出不同的響應

下面是"不叫"按鈕的click事件處理程序

在Player類中,player1.SelectLandLordEnd的具體代碼如下:

public void SelectLandLordEnd()
{
 DConsole.PaintLandLord(true); //傳遞true給該方法,在窗口中央顯示地主三張牌的具體點數
 if (this.isLandLord) //如果自己是地主的話
 {
  foreach (Poker poker in DConsole.LandLordPokers) //把這三張牌添加到自己的牌組中
  {
   this.pokers.Add(poker);
  }
  this.sort(); //重新排序
  this.Paint(); //重新顯示自己的牌
 }
}

地主的權限傳遞就這麼多了,可能寫的比較亂,但是並不復雜,相信大家仔細多看幾遍應該能夠明白的.。如果那裡有錯誤的話歡迎在下面留言欄反饋。謝謝!

下面是server類裡面的監聽客戶端消息的程序:

(由於篇幅所限,這裡只貼出與地主權限傳遞有關的代碼)

public void AccpetClient1Data() //監聽客戶端1的消息
{
 NetworkStream Ns1 = client1.GetStream();
 string str1 = "";
 while (true)
 {
  PokerGroup pg = new PokerGroup();
  byte[] bytes1 = new byte[108];
  Ns1.Read(bytes1, 0, 108);
  str1 = Encoding.Default.GetString(bytes1);
(省略部分)
  if (str1.StartsWith("AreYouLandLord"))
  {
   if (DConsole.LandLordNum == 1) //如果默認地主為服務器,那麼根據文章開頭的權限傳遞順序圖,server-client2-client1,client1為最後一個玩家,所以需要和牌重新來過
   {
    DConsole.Restart();
    continue;
   }
    DConsole.player1.areYouLandLord = true; //當默認地主不是服務器時,設置服務器的叫地主權限為true,當timer控件讀取到該值時,服務器的叫地主和不叫按鈕馬上就會顯示出來.
                     continue;
  }
  if (str1.StartsWith("IamLandLord")) //客戶端1為地主
  {
   DConsole.lblClient1Name.Text += "(地主)";
   DConsole.lblClient1Name.ForeColor = System.Drawing.Color.Red;
   SendDataForClient("ClientIsLandLord", 2); //通知客戶端2,客戶端1為地主
   Thread.Sleep(sleep);
   DConsole.PaintClient(20, 1);
   SendDataForClient("LandLordPokers", DConsole.LandLordPokers, 1); //地主已選出,把牌發送給所有玩家
   Thread.Sleep(sleep);
   SendDataForClient("LandLordPokers", DConsole.LandLordPokers, 2); //地主已選出,把牌發送給所有玩家
   DConsole.player1.SelectLandLordEnd(); //該方法的具體代碼請看下文
   continue;
  }
 }
}
/// <summary>
/// 循環接收客戶端2的請求數據
/// </summary>
public void AccpetClient2Data()
{
 NetworkStream Ns2 = client2.GetStream();
 string str1 = "";
 while (true)
 {
  PokerGroup pg = new PokerGroup();
  byte[] bytes2 = new byte[108];
  Ns2.Read(bytes2, 0, 108);
  str1 = Encoding.Default.GetString(bytes2);
(省略部分)
  if (str1.StartsWith("AreYouLandLord")) //客戶端2不要地主
  {
   if (DConsole.LandLordNum == 2) //如果默認地主為客戶端1,那麼根據文章開頭的權限傳遞順序圖,client1-server-client2,client2為最後一個玩家,所以需要和牌重新來過
   {
    DConsole.Restart();
    continue;
   }
   SendDataForClient("AreYouLandLord", 1); //如果默認地主不是客戶端1的話,按照順序把叫地主權限傳遞給client1,client1的處理程序上文已經列出
   continue;
  }
  if (str1.StartsWith("IamLandLord") ) //客戶端2為地主
  {
   DConsole.lblClient2Name.Text += "(地主)";
   DConsole.lblClient2Name.ForeColor = System.Drawing.Color.Red;
   SendDataForClient("LandLordPokers", DConsole.LandLordPokers, 1);
   SendDataForClient("LandLordPokers", DConsole.LandLordPokers, 2);
   SendDataForClient("ClientIsLandLord", 1);
   DConsole.PaintClient(20, 2);
   DConsole.player1.SelectLandLordEnd();
   continue;
  }
 }
}

private void btnNotLandLord_Click(object sender, EventArgs e)
{
 this.player1.areYouLandLord = false;
 this.player1.isLandLord = false;
 this.btnNeedLandLord.Visible = false;
 this.btnNotLandLord.Visible = false;
 if (this.server != null) //玩家是服務端
 {
  if (DConsole.LandLordNum == 3) 如果client2是默認地主,根據權限傳遞順序client2-client1-server,server為最後玩家,如果server不叫地主,只能和牌重來
   {
    DConsole.Restart();
    return;
   }
   this.server.SendDataForClient("AreYouLandLord",2); //如果client2不是默認地主,就把權限傳遞給client2
 }
 if (this.client != null) //如果玩家是客戶端
 {
  this.client.SendDataForServer("AreYouLandLord"); //告訴服務器自己不叫
 }
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved