zoukankan      html  css  js  c++  java
  • Silverlight+WCF 新手实例 象棋 房间状态更新(二十)

    在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示

    这节开始,标题里就去掉"回归WCF通讯应用"几字了。

    上节我们成功实现了进入房间,服务端也收到用户进入房间的请求了,这节,我们服务端收到进入房间请求后,通知在房间大门外的人更新房间状态。

    我们要增加一个回调方法,ICallBack接口那,忘记的人回去看看WCF通讯那几篇(十四到十七节)。

    方法如下,以前说过了,回调的方法是给客户端实现的,服务端只管调就行了:

    using System.ServiceModel;

    namespace GameService
    {
        
    interface ICallBack
        {
            [OperationContract(IsOneWay 
    = true)]
            
    void NotifyRoomUpdate(Room room);
        }
    }

    那我们回到服务端进入房间的代码,只管调用一下了:

    我们看下这段进入房间代码:

     public bool EnterRoom(Player player, int roomID)
            {
                
    bool roomInDic = roomList.ContainsKey(roomID);//房间列表里有没有
                Room room = roomInDic ? roomList[roomID] : new Room();//有就直接拿了,没有就直接New一个新的
                if (!room.RedInChair)//房间的红色座位有没有人
                {
                    room.RedInChair 
    = player.ColorValue == 1;
                }
                
    if (!room.BlackInChair)//房间的黑色座位有没有人
                {
                    room.BlackInChair 
    = player.ColorValue == 2;
                }
                
    if (!roomInDic)//房间列表里没有,添加到房间列表中
                {
                    room.ID 
    = roomID;
                    roomList.Add(roomID, room);
                }
                
                ChangeRoom(player, roomID);
    //改变玩家的房间标记,待会实现

                
    //这里是新加的,通知0房间的人[未进入房间的人]都更新此房间状态
                foreach (KeyValuePair<Guid,Player> item in playerList[0])
                {
                    item.Value.CallBack.NotifyRoomUpdate(room);
                }
                
    return true;
            }

    foreach之前的代码是上节的了,这里我们只增加了一个foreach来循环0房间的用户,通知他们更新房间状态。

    同样的,如果是退出房间,也要加一个foreach,代码如下:

    public void OutRoom(Player player, int roomID)
            {
                
    if (roomID > 0)
                {
                    Room room 
    = roomList[roomID];
                    
    if (player.ColorValue == 1)//如果退出玩家是红色座位
                    {
                        room.RedInChair 
    = false;
                    }
                    
    if (player.ColorValue == 2)//如果退出玩家是红色黑色座位
                    {
                        room.BlackInChair 
    = false;
                    }
                    ChangeRoom(player, 
    0);//改变玩家的房间标记,待会实现

                    
    //这里是新加的,通知0房间的人[未进入房间的人]都更新此房间状态
                    foreach (KeyValuePair<Guid, Player> item in playerList[0])
                    {
                        item.Value.CallBack.NotifyRoomUpdate(room);
                    }

                }
            }

    当我们看到同样的代码循环重复的出现的时候,我们会感到皮痒,我们得把它封装起来,弄成一个小函数调用。

    于是,我新建了一个Notify通知类。用于把所有的通知都集成到这里来。

    皮痒了,GameService项目里新建一个类[示例源代码里会放到一个文件夹Notify下]:

    namespace GameService
    {
        
    /// <summary>
        
    /// 通知 by 路过秋天
        
    /// </summary>
        public class Notify
        {

        }
    }

    我们添加一个新方法,叫Room, 我们把那foreach的方法Copy过来,就是如下代码了:

    namespace GameService
    {
        
    /// <summary>
        
    /// 通知 by 路过秋天
        
    /// </summary>
        public class Notify
        {
            
    internal static void Room(Dictionary<int, Dictionary<Guid, Player>> playerList, Room room)
            {
                
    //这里是新加的,通知0房间的人[未进入房间的人]都更新此房间状态
                foreach (KeyValuePair<Guid, Player> item in playerList[0])
                {
                    item.Value.CallBack.NotifyRoomUpdate(room);
                }
            }
        }
    }

    有了这个,我们回去把房间进入的和退出的foreach都改成Notify.Room(playerList,room);就OK了。

    大伙自己改了,这里不再贴代码出来了。

    成了,服务端写完了,那客户端要实现回调的方法的,我们编绎一下GameService项目,不编绎是不行的,我们加了接口,

    客户端得“更新服务引用”,

    怎么更新?以前截过图的,回去看上一节:Silverlight+WCF 新手实例 象棋 回归WCF通讯应用-进入房间(十九)

    好了,回客户端了,回哪?当然回到Room.xmal那了,我们要更新房间的状态的。

    namespace NewChessProject
    {
        
    public partial class Room : UserControl
        {
            
    public Room()
            {
                InitializeComponent();
                Game game 
    = new Game();
                game.CreateGameRoom(
    30);
                game.DrawIn(LayoutRoot);

                
    //这里实现ICallBack的方法
                App.client.NotifyRoomUpdateReceived += new EventHandler<GameService.NotifyRoomUpdateReceivedEventArgs>(client_NotifyRoomUpdateReceived);
            }

            
    void client_NotifyRoomUpdateReceived(object sender, GameService.NotifyRoomUpdateReceivedEventArgs e)
            {
                
    //看这里看这里,这里实现啦
            }

        }
    }

    这里等待服务端调用时,执行的方法了,现在实现了。

    嘿嘿,皮又痒了,三行的代码,又封装出一个UpdateRoomState方法来了。

     void client_NotifyRoomUpdateReceived(object sender, GameService.NotifyRoomUpdateReceivedEventArgs e)
            {
                
    //这里实现啦
                if (game.GameRoomList != null && e.room != null)
                {
                    UpdateRoomState(e.room, game.GameRoomList[e.room.ID 
    - 1]);
                }
            }
            
    void UpdateRoomState(GameService.Room gsRoom, GameRoom room)
            {
                room.RedPlayerInChair 
    = gsRoom.RedInChair;
                room.BlackPlayerInChair 
    = gsRoom.BlackInChair;
                room.ReDraw();
            }

    最后还调用了room的ReDraw()方法。咦?room是没这个方法的,没有就加,咦什么咦。

    回到GameRoom.cs里去,加个ReDraw方法,就两行代码了,大伙别急:

    public void ReDraw()
    {
    redChair.Fill 
    = new RadialGradientBrush(RedPlayerInChair ? Colors.Blue : Colors.Red, Colors.Transparent);
    blackChair.Fill 
    = new RadialGradientBrush(BlackPlayerInChair ? Colors.Blue : Colors.Black, Colors.Transparent);
    }

    OK,客户端写完了,我们F5运行看结果:

    启动一个浏览器,登陆后我们不动,同时复制地址,新开一个浏览器,也登陆进去如下图:

    好,我们点击第二个浏览器进去第一个红色房间:

    看,第一个房间的状态变了。至此,我们顺利完成了房间状态的通知更新。

    那退出房间哪去了?别急,Index页面还没东西呢。

    版权声明:本文原创发表于 博客园,作者为 路过秋天 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
    个人微信公众号
    创业QQ群:617713515
    Donation(扫码支持作者):支付宝:
    Donation(扫码支持作者):微信:
  • 相关阅读:
    Hibernate延迟加载
    java.io.FileNotFoundException: antlr-2.7.7.jar (系统找不到指定的路径。)[待解决]
    Eclipse中复制项目重命名后重新发布,项目名在地址栏仍然是原来的项目名”的问题
    Tomcat服务器启动失败:Could not publish server configuration for Tomcat v8.0 Server at localhost. Multiple Contexts have a path of
    SSH整合:Unable to instantiate Action, employeeAction, defined for 'emp-list' in namespace '/'employeeAction
    ApplicationContext详解以及多个ApplicationContext.xml的相互引用
    Tomcat启动失败:Server Tomcat v8.0 Server at localhost was unable to start within 45 seconds
    三大框架你理解多少?
    通过命令行查询可用的包的版本号
    使用create-react-app命令创建一个项目, 运行npm run eject报错
  • 原文地址:https://www.cnblogs.com/cyq1162/p/1780733.html
Copyright © 2011-2022 走看看