VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Objective-C编程 >
  • c#网络版斗地主之地主权限的传递

制作者:剑锋冷月 单位:无忧统计网,www.51stat.net
 

  本文是对C#网络版斗地主的总结。

  首先服务器使用一个随机数来随即选出默认地主。然后发送信息给选出来的玩家。玩家接收到信息后显示两个按钮“叫地主”,“不叫”。如果选择不叫,则把可以叫地主的权限发送给另外一个玩家,如果另外两个玩家都不要的话,就执行Restart()方法重新发牌。

  叫地主权限的传递顺序如下图所示:

C#网络版斗地主——地主权限的传递

  具体实现方法:

  服务器得到一个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");//告诉服务器自己不叫
            }
        }

 

  系列文章:

  C#写的网络版斗地主

  C#网络版斗地主——网络部分实现

  C#网络版斗地主——出牌权限的传递

 

 

  客户端的循环接收数据程序会分析服务端发送过来的数据,在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;
                }
                (后面省略)
            }
        }



相关教程