命令模式-坦克大战-c#

概要

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。

类图

命令模式

运行

代码 

using System;

namespace 命令模式
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            Client client = new Client();
            client.main();
            Console.ReadLine();
        }
    }
    // 抽象层
    class InvokerTank
    {
        ICommand scmd;
        ICommand rcmd;
        public InvokerTank(ICommand scmd,ICommand rcmd)
        {
            this.scmd = scmd;
            this.rcmd = rcmd;
        }
        public void sort()
        {
            this.scmd.execute();
        }
        public void run()
        {
            this.rcmd.execute();
        }
    }
    interface ICommand
    {
        void execute();
    }
    class Receiver
    {
        public void sort()
        {
            Console.WriteLine("sort");
        }
        public void run()
        {
            Console.WriteLine("run");
        }
    }
    // 实现层
    class SortCommand : ICommand
    {
        Receiver receiver;

        public SortCommand(Receiver receiver)
        {
            this.receiver = receiver;
        }
        public void execute()
        {
            this.receiver.sort();
        }
    }
    class RunCommand : ICommand
    {
        Receiver receiver;
        public RunCommand(Receiver receiver)
        {
            this.receiver = receiver;
        }
        public void execute()
        {
            this.receiver.run();
        }
    }
    class Client
    {
        public void main()
        {
            Receiver receiver = new Receiver();
            SortCommand sortCommand = new SortCommand(receiver);
            RunCommand runCommand = new RunCommand(receiver);
            InvokerTank tank = new InvokerTank(sortCommand, runCommand);
            tank.sort();
            tank.run();
        }
    }

}

代码优化

优化方向:消除冗余

1.加深了抽象,把请求和服务都做了一个接口抽象,因为是同步请求,说以请求和响应的接口是一样的;

2.命令行提取了一个基类,消除了两个server 成员变量的冗余。

3.添加量一个B70Receiver,增强了comand的可选择范围。

运行效果

代码

using System;

namespace 命令模式
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            Client client = new Client();
            client.main();
            Console.ReadLine();
        }
    }
    // 抽象层
    interface IFunctions
    {
        void sort();
        void run();
    }
    interface ICommand
    {
        void execute();
    }
    // 实现层
    class InvokerTank: IFunctions
    {
        ICommand scmd;
        ICommand rcmd;
        public InvokerTank(ICommand scmd, ICommand rcmd)
        {
            this.scmd = scmd;
            this.rcmd = rcmd;
        }
        public void sort()
        {
            this.scmd.execute();
        }
        public void run()
        {
            this.rcmd.execute();
        }
    }
    class Receiver: IFunctions
    {
        public virtual void sort()
        {
            Console.WriteLine("sort");
        }
        public virtual void run()
        {
            Console.WriteLine("run");
        }
    }
    class B70Receiver: Receiver
    {
        public override void sort()
        {
            Console.WriteLine("sort:70");
        }
    }
    abstract class Command : ICommand
    {
        protected Receiver receiver;
        protected Command(Receiver receiver)
        {
            this.receiver = receiver;
        }
        public abstract void execute();
    }
    class SortCommand : Command
    {
        public SortCommand(Receiver receiver):base(receiver){}
        public override void execute()
        {
            this.receiver.sort();
        }
    }
    class RunCommand : Command
    {
        public RunCommand(Receiver receiver):base(receiver){}
        public override void execute()
        {
            this.receiver.run();
        }
    }
    class Client
    {
        public void main()
        {
            Receiver receiver = new Receiver();
            B70Receiver b70Receiver = new B70Receiver();
            SortCommand sortCommand = new SortCommand(b70Receiver);
            RunCommand runCommand = new RunCommand(receiver);
            InvokerTank tank = new InvokerTank(sortCommand, runCommand);
            tank.sort();
            tank.run();
        }
    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
写完单机版http://blog.csdn.net/xiaoxiao108/archive/2010/12/18/6084473.aspx游戏后 再写个网络版玩玩。 开发工具vs2008 网络版实现方法很简单 1.一个服务端,多个客户端 2.服务端开个端口监听,当一个客户端程序后连接到服务端后,服务端分配个编号给客户端作为他的坦克编号 3.当有新坦克创建,坦克移动,等操作时,客户端发送数据到服务端,服务端再把数据发送到所有的客户端来实现网络游戏的同步 具体实现代码 1.服务端开启服务代码 public void Start() { //开启udp线程 Thread t = new Thread(UDPThread); t.IsBackground = true; t.Start(); //开启tcp服务 TcpListener tl = new TcpListener(TCP_PORT); tl.Start(); while (true) { TcpClient tc = tl.AcceptTcpClient(); Stream ns = tc.GetStream(); BinaryReader br = new BinaryReader(ns); int udpPort = br.ReadInt32();//br.Close();不能关闭br BinaryWriter bw = new BinaryWriter(ns); bw.Write(ID++); IPEndPoint rep = (IPEndPoint)tc.Client.RemoteEndPoint; Client c = new Client(rep.Address.ToString(), udpPort); clients.Add(c); Console.WriteLine("A Client TCP Connect! Addr- " + rep.Address.ToString() + ":" + rep.Port); } } 2.服务端udp数据接收转发代码 private void UDPThread() { Console.WriteLine("UDP thread started at port :" + UDP_PORT); byte[] buf = new byte[1024]; UdpClient uc = new UdpClient(UDP_PORT);//// 跟java有区别 如果这句话放到while外面 就不能接受第二个坦克连入 IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 0); while (true) { buf = uc.Receive(ref ipep); Console.WriteLine("a udp packet received! from " + ipep.Address + ":" + ipep.Port); //把收到的数据转发给每一个客户端 for (int i = 0; i < clients.Count; i++) { Client c = clients[i]; UdpClient _uc = new UdpClient(); _uc.Connect(c.ip, c.udpPort); _uc.Send(buf, buf.Length); } } } 3.客户端连接代码 public void Connect(string ip, int port) { this.ip = ip; TcpClient client = new TcpClient(); client.Connect(ip, port); Stream ns = client.GetStream(); BinaryWriter bw = new BinaryWriter(ns); bw.Write(udpPort); BinaryReader br = new BinaryReader(ns); //bw.Close();不能关闭bw //从服务器端取到服务器分配的坦克编号 int id = br.ReadInt32(); tc.myTank.ID = id; //编号为偶数的设置为坏蛋 if (id % 2 == 0) tc.myTank.Good = false; else tc.myTank.Good = true; //可以在“输出窗口”看到下面的调试代码 Debug.WriteLine("Connected to server! and server give me a ID:" + id); br.Close(); ns.Close(); client.Close(); TankNewMsg msg = new TankNewMsg(tc.myTank); Send(msg); //开启接收线程 Thread t = new Thread(UDPRecvThread); t.IsBackground = true; t.Start(); } 4.坦克加入消息代码发送代码 public void Send(UdpClient uc, string ip, int udpPort) { uc.Connect(ip, udpPort); //程序中用 | 来分割发送的内容 string str = msgType + "|" + tank.ID + "|" + tank.x + "|" + tank.y + "|" + (int)tank.dir + "|" + tank.Good; uc.Send(Encoding.UTF32.GetBytes(str), Encoding.UTF32.GetBytes(str).Length); } 5.坦克加入消息解析代码 public void Parse(byte[] b) { string str = Encoding.UTF32.GetString(b); string[] strs = str.Split('|'); int id = Convert.ToInt32(strs[1]); //如果数据包里是自己的坦克不处理 if (id == tc.myTank.ID) { return; } int x = Convert.ToInt32(strs[2]); int y = Convert.ToInt32(strs[3]); Direction dir = (Direction)Convert.ToInt32(strs[4]); bool good = Convert.ToBoolean(strs[5]); Boolean exist = false; for (int i = 0; i < tc.tanks.Count; i++) { Tank t = tc.tanks[i]; if (t.ID == id) { exist = true; break; } } //如果坦克不存在就创建出来 if (!exist) { TankNewMsg msg = new TankNewMsg(tc.myTank); tc.nc.Send(msg); //Tank t = new Tank(x, y, good, tc);//java中是这样写得Tank t = new Tank(x,y,good,dir,tc) Tank t = new Tank(x, y, good, dir, tc); //有可能是老坦克 给新坦克发包 所以要家dir参数 t.ID = id; tc.tanks.Add(t); } } 6.坦克移动消息 public void Send(UdpClient uc, string ip, int udpPort) { uc.Connect(ip, udpPort); //程序中用 | 来分割发送的内容 string str = msgType + "|" + id + "|" + x + "|" + y + "|" + Convert.ToInt32(dir); uc.Send(Encoding.UTF32.GetBytes(str), Encoding.UTF32.GetBytes(str).Length); } public void Parse(byte[] b) { string str = Encoding.UTF32.GetString(b); string[] strs = str.Split('|'); int id = Convert.ToInt32(strs[1]); //如果数据包里是自己的坦克不处理 if (id == tc.myTank.ID) { return; } int x = Convert.ToInt32(strs[2]); int y = Convert.ToInt32(strs[3]); Direction dir = (Direction)Convert.ToInt32(strs[4]); for (int i = 0; i < tc.tanks.Count; i++) { Tank t = tc.tanks[i]; if (t.ID == id) { t.dir = dir; t.x = x; t.y = y; break; } } } 7.子弹消息处理代码 public void Send(UdpClient uc, string ip, int udpPort) { uc.Connect(ip, udpPort); //程序中用 | 来分割发送的内容 string str = msgType + "|" + m.tankID + "|" + m.x + "|" + m.y + "|" + (int)m.dir + "|" + m.good; uc.Send(Encoding.UTF32.GetBytes(str), Encoding.UTF32.GetBytes(str).Length); } public void Parse(byte[] b) { string str = Encoding.UTF32.GetString(b); string[] strs = str.Split('|'); int tankID = Convert.ToInt32(strs[1]); if (tankID == tc.myTank.ID) { return; } int x = Convert.ToInt32(strs[2]); int y = Convert.ToInt32(strs[3]); Direction dir = (Direction)Convert.ToInt32(strs[4]); bool good = Convert.ToBoolean(strs[5]); Missile m = new Missile(tankID, x, y, good, dir, tc); tc.missiles.Add(m); } 单机测试时 先运行服务端 再运行多个客户端就ok 多机联网游戏时修改下 nc.Connect("127.0.0.1", 8888);中的ip地址就可以在局域网内玩了 如果连接不上 可以关了防火墙试试看 private void Form1_Load(object sender, EventArgs e) { myTank = new Tank(50, 20, true, this);//放到前面 this不能用 //y轴比java的减少了30 nc = new NetClient(this); nc.Connect("127.0.0.1", 8888); //nc.connect("192.168.1.168",8888); //nc.connect("10.10.10.1",8888); } 如果你发现有什么不合理的,需要改进的地方,联系328452421@qq.com 朱晓 (泰山学院)。相互交流 谢谢
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值