haveOrder(出牌權限)傳遞的具體實現:
在服務器選擇地主時,把出牌權限一並傳給地主,所以出牌是由地主開始的。這裡我先假設地主為服務器。
服務器在叫地主後,出了本局第一組牌,下面看一下出牌按鈕的處理程序:
private void btnLead_Click(object sender, EventArgs e) //出牌按鈕的事件處理程序
{
if (player1.lead())//嘗試出牌,該方法的代碼見上文,如果出牌成功,執行以下代碼
{
this.btnLead.Visible = false;
this.btnPass.Visible = false;//隱藏出牌和不要按鈕
if (this.server != null) //當玩家為服務器時
{
server.SendDataForClient("SPokerCount" + Convert.ToString(this.player1.pokers.Count), 1); //發送自己牌的剩余張數給clIEnt1
Thread.Sleep(100);//延遲100毫秒
server.SendDataForClient("SPokerCount" + Convert.ToString(this.player1.pokers.Count), 2);發送自己牌的剩余張數給clIEnt2
Thread.Sleep(100);
server.SendDataForClient("server", DConsole.leadPokers, 1);//發送自己出的牌組給clIEnt1
Thread.Sleep(100);
server.SendDataForClient("server", DConsole.leadPokers, 2);//發送自己出的牌組給clIEnt2
Thread.Sleep(100);
if (this.player1.pokers.Count == 0 && DConsole.IsStart) //當server端牌的張數為0並且游戲已經開始時
{
DConsole.Winer = 1; //勝利者為1,即server,這裡是計分系統,很簡單,不贅述
DConsole.Restart();//重新開始游戲
}
else
{
server.SendDataForClient("Order", 2); //這裡就是傳遞權限的關鍵代碼,當server端出牌並且牌沒有出完時,傳遞出牌權限給server端的下家,根據權限傳遞順序,server-client2-clinet1,所以這裡把出牌權限傳遞給clIEnt2
}
DConsole.player1.haveOrder = false; //自己的出牌權限已經消失
}
if (this.clIEnt != null) //當玩家為客戶端時
{
clIEnt.SendDataForServer("PokerCount" + Convert.ToString(this.player1.pokers.Count)); //發送客戶端牌的剩余張數給服務器,服務器會處理並轉發給另一個客戶端
Thread.Sleep(500);
client.SendDataForServer("client", DConsole.leadPokers);//發送客戶端出牌牌組給服務器,服務接收到該消息後,就知道客戶端1或者客戶端2已出牌,如果該消息是客戶端1發出的,根據權限傳遞順序clIEnt2-clinet1-server,服務器會獲得出牌權限,如果該消息是客戶端2發出的,服務器會發送消息給客戶端1使客戶端1擁有出牌權限
Thread.Sleep(100);
this.player1.haveOrder = false; //自己的出牌權限消失
}
player1.g.Clear(this.BackColor);
player1.Paint();
DConsole.PaintPlayer1LeadPoker();
}
else
{
DConsole.Write("[系統消息]:您出的牌不符合規則!");
}
}
來看看server類中有關出牌權限傳遞的相關處理程序:
/// <summary>
/// 循環接收客戶端1的請求數據
/// </summary>
public void AccpetClIEnt1Data()
{
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);
//(省略N行)
if (str1.StartsWith("client")) //收到客戶端1的clIEnt消息,該消息表示客戶端1出的牌
{
SendDataForClIEnt(str1, 2);
Thread.Sleep(sleep);
str1 = str1.Replace("clIEnt", "");
pg.GetPokerGroup(Encoding.Default.GetBytes(str1));
DConsole.leadedPokerGroups.Add(pg); //這裡在add之前會對該牌組進行驗證和排序
DConsole.PaintPlayer2LeadPoker(pg);
DConsole.WriteLeadedPokers();
if (!DConsole.IsRestart)
{
DConsole.player1.haveOrder = true; //client1出牌後歸server出牌,前提是沒有Restart,Restart後出牌權限消失,根據權限傳遞順序client2-clinet1-server,這裡接收到的是clIEnt1的出牌,說明輪到server出牌了.
}
else
{
DConsole.IsRestart = false;//當檢測到已經Restart時,復位Restart使它還原為false
}
continue;
}
//ClIEnt放棄出牌,權限交給服務器
if (str1.StartsWith("Pass"))
{
DConsole.gPlayer2LeadPoker.Clear(DConsole.backColor);
DConsole.gPlayer2LeadPoker.DrawString("不要", new System.Drawing.Font("宋體", 20), System.Drawing.Brushes.Red,5,5);
DConsole.player1.haveOrder = true;
SendDataForClient("ClIEntPass", 2); //告訴客戶端2,客戶端1pass了
continue;
}
if (str1.StartsWith("IamIsBiggest"))//客戶端1說他的牌是最大的,所以要把自己的IsBiggest設置為false,因為最大的牌只能有一個
{
DConsole.player1.isBiggest = false;
this.SendDataForClient("NoBiggest", 2); //同時要轉發給client2,讓clIEnt2把自己的IsBiggest屬性設置為false
continue;
}
//(省略N行)
}
}
/// <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);
(省略N行)
if (str1.StartsWith("client"))//收到客戶端2的clIEnt消息,該消息表示客戶端2出的牌
{
SendDataForClIEnt(str1, 1);
Thread.Sleep(sleep);
str1 = str1.Replace("clIEnt", "");
pg.GetPokerGroup(Encoding.Default.GetBytes(str1));
DConsole.leadedPokerGroups.Add(pg);//這裡在add之前會對該牌組進行驗證和排序
DConsole.PaintPlayer3LeadPoker(pg);
DConsole.WriteLeadedPokers();
if (!DConsole.IsRestart)
{
SendDataForClient("Order", 1); //client2出牌後歸client1出牌,前提是沒有Restart,Restart後出牌權限消失,根據權限傳遞順序server-client2-clinet1,這裡接收到的是clIEnt2的出牌,說明輪到clinet1出牌了.
}
else
{
DConsole.IsRestart = false; //當檢測到已經Restart時,復位Restart使它還原為false供下次使用
}
System.Threading.Thread.Sleep(sleep);
continue;
}
//Client2放棄出牌,權限交給ClIEnt1
if (str1.StartsWith("Pass"))
{
DConsole.gPlayer3LeadPoker.Clear(DConsole.backColor);
DConsole.gPlayer3LeadPoker.DrawString("不要", new System.Drawing.Font("宋體", 20), System.Drawing.Brushes.Red, 5, 5);
SendDataForClient("ClIEntPass", 1);//告訴客戶端1,客戶端2pass了
Thread.Sleep(500);
SendDataForClIEnt("Order", 1);
continue;
}
if (str1.StartsWith("IamIsBiggest"))//客戶端2說他的牌是最大的,所以要把自己的IsBiggest設置為false,因為最大的牌只能有一個
{
DConsole.player1.isBiggest = false;
this.SendDataForClient("NoBiggest", 1);//同時要轉發給client21,讓clIEnt1把自己的IsBiggest屬性設置為false
continue;
}
(省略N行)
}
}