C#中国象棋网络版源代码(五)-核心业务类Game Class

中国象棋网络版核心业务类Game

非常重要的类,象棋程序所有业务封装在Game类.

学习要点:

1.public
static Game CurrentGame 游戏实例。
2.监听程序部分
3.命令分析部分(消息接收及处理)
4.多线程访问主线程创建的控件
5.事件回调
6.业务控制,如接收命令->分析->处理->界面展示->刷新棋盘
7.学习业务逻辑部分与窗体控制之间关系及运作。

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Windows.Forms;
using System.Drawing;

/********************************************************************************
* 本网站内容允许非商业用途的转载,但须保持内容的原始性并以链接的方式注明出处,
* 本公司保留内容的一切权利。
* 凡注明易学原创的源代码及文档不得进行商业用途转载!!! *

*********************************************************************************
* 易学网祝您学业有成!* by www.vjsdn.com
*********************************************************************************/


namespace www.vjsdn.com.ChineseChess.Library
{
    /// <summary>
    /// 游戏控制类
    /// </summary>
    public class Game
   {
       private int LISTING_PORT = 26978; //用于监听的端口号
      
       private TcpListener _Listener = null; //本地消息监听器
       private Thread _ListenerThread = null; //监听器使用的线程
       private bool _ListenerRunning = false; //标志监听器是否运行
      
       private bool _IsPlayGame = false; //标志是否开始游戏
      
       private Player _PlayerRed = null; //红方
       private Player _PlayerBlack = null; //黑方(远程玩家)
      
       private ChessBoard _chessBoard = null; //棋盘类
       private ConnectionCallBack _callBack = null; //连接远程玩家的回调函数
       private GameControlPanel _controlPanel = null; //游戏控制面板
      
       private static Game _currentGame = null; //当前游戏实例
       public static Game CurrentGame
      {
          get
         {
             if (_currentGame == null) _currentGame = new Game();
             return _currentGame;
         }
      }
      
       public bool IsPlaying { get { return _IsPlayGame; } }
       public ChessBoard ChessBoard { get { return _chessBoard; } set { _chessBoard = value; } }
       public Player PlayerRed { get { return _PlayerRed; } set { _PlayerRed = value; } }
       public Player PlayerBlack { get { return _PlayerBlack; } set { _PlayerBlack = value; } }
       public GameControlPanel ControlPanel { get { return _controlPanel; } set { _controlPanel = value; } }
      
       /// <summary>
       /// 启动游戏.参数:是否通知远程玩家启动游戏
       /// </summary>
       public void StandBy( bool notifyRemote)
      {
          this.StandBy();
         
          if (_PlayerBlack != null && notifyRemote)
          this.SendCommand(_PlayerBlack.IpAddress, "BEGIN:");
      }
      
       //准备就绪
       public void StandBy()
      {
          this.StartListener();
         
         _controlPanel.SetButtonStart( false);
         _controlPanel.SetButtonLost( true);
         _controlPanel.SetButtonRegret( true);
         
         _controlPanel.Reset();
         _chessBoard.Reset(); //画棋盘
         
         _PlayerRed.Ready = true; //准备好
         _chessBoard.EnableMove = true;
      }
      
       /// <summary>
       /// 开始游戏
       /// </summary>
       public void Play( bool move)
      {
         _IsPlayGame = true;
         
          if (move) //启动红方计时器
         {
            _controlPanel.StartTimer(ChessColor.Red);
            _controlPanel.StopTimer(ChessColor.Black);
         }
          else //黑方计时器
         {
            _controlPanel.StartTimer(ChessColor.Black);
            _controlPanel.StopTimer(ChessColor.Red);
         }
      }
      
       /// <summary>
       /// 开始游戏,启动本地监听
       /// </summary>
       private void StartListener()
      {
          string localIP = Dns.GetHostAddresses(Dns.GetHostName())[0].ToString();
         
          this.DoStartListening(localIP, LISTING_PORT);
      }
      
       //发送坐标到远程玩家
       public void SendPointToRemote(ChessPoint fromPoint, ChessPoint targetPoint)
      {
          string cmd = string.Format("MOVE:{0},{1},{2},{3}", fromPoint.X, fromPoint.Y, targetPoint.X, targetPoint.Y);
          this.SendCommand(_PlayerBlack.IpAddress, cmd);
      }
      
       #region 网络连接部分
      
       private void DoStartListening( string ip, int port)
      {
          if (_ListenerRunning) return;
         
          //构建监听器
         _Listener = new TcpListener(IPAddress.Parse(ip), port);
         _Listener.Start(255);
         _ListenerRunning = true;
         
          //启动线程
         _ListenerThread = new Thread( new ThreadStart(DoStartServerListener));
         _ListenerThread.IsBackground = true;
         _ListenerThread.Start();
      }
      
       private void StopListening()
      {
          if (_ListenerRunning)
         {
            _ListenerRunning = false;
            _ListenerThread.Abort(101);
            _ListenerThread = null;
            _Listener.Stop();
         }
      }
      
       /// <summary>
       ///启动服务器程序.
       /// </summary>
       private void DoStartServerListener()
      {
          //监听客户连线请求
          while (_ListenerRunning)
         {
             try
            {
                if (_Listener == null) return; //防止其它地方关闭监听器
               
               Socket socket = _Listener.AcceptSocket(); //有客户请求连接
                if (socket == null) continue;
               
                byte[] buffer = new Byte[socket.ReceiveBufferSize];
                int i = socket.Receive(buffer); //接收请求数据.
                if (i <= 0) continue;
                string cmd = Encoding.Default.GetString(buffer).Replace("/0", "");
               ProcessCommand(socket, cmd.Trim()); //处理命令
               socket.Close(); //关闭连接
            }
             catch (Exception ex)
            {
                if (ex is ThreadAbortException)
               {
                   if ((ex as ThreadAbortException).ExceptionState.ToString() == "101")
                  {
                     _ListenerRunning = false;
                  }
               }
                else
               {
                  Msg.ShowException(ex);
               }
            }
         }
      }
      
       /// <summary>
       /// 处理命令.命令格式: [命令字符+":"+参数],如: [MOVE:2,2]
       /// </summary>
       private void ProcessCommand(Socket socket, string cmd)
      {
          string remoteIp = socket.RemoteEndPoint.ToString();
         remoteIp = remoteIp.Substring(0, remoteIp.IndexOf(":"));
         
          string[] cmds = cmd.Split( new char[] { char.Parse(":") });
          if (cmds.Length < 1) return; //非法命令
         
          #region 悔棋
          //玩家悔棋
          if (cmds[0].ToUpper() == "REGRET")
         {
             if (Msg.AskQuestion("对方想悔棋,同意吗?"))
            SendCommand(remoteIp, "REGRET_YES:"); //接受悔棋
             else
            SendCommand(remoteIp, "REGRET_NO:"); //拒绝悔棋
             return;
         }
         
          //同意悔棋
          if (cmds[0].ToUpper() == "REGRET_YES")
         {
             //执行悔棋动作
             //...
            Msg.Warning("走棋前要三思啊!!!");
             return;
         }
         
          //拒绝悔棋
          if (cmds[0].ToUpper() == "REGRET_NO")
         {
            Msg.Warning("对方不同意悔棋!");
             return;
         }
          #endregion
         
          #region 请求玩游戏
          //有玩家请求玩游戏
          if (cmds[0].ToUpper() == "JOIN")
         {
             if (Game.CurrentGame.IsPlaying)
            {
               SendCommand(remoteIp, "GAME_RUNNING:"); //邀请的玩家正在与其它玩家下棋
            }
             else
            {
                string name = cmds[1]; //玩家名称
                string msg = string.Format("玩家’{0}’想和您玩游戏,同意吗?", name);
                if (Msg.AskQuestion(msg))
               {
                  _PlayerBlack = new Player(ChessColor.Black, name);
                  _PlayerBlack.IpAddress = remoteIp;
                  
                   string myName = this.GetPlayerName();
                  SendCommand(remoteIp, "JOIN_YES:" + myName); //接受请求
               }
                else
               SendCommand(remoteIp, "JOIN_NO:"); //拒绝请求
            }
             return;
         }
         
          //邀请的玩家正在与其它玩家下棋
          if (cmds[0].ToUpper() == "GAME_RUNNING")
         {
            Msg.Warning("您邀请的玩家正在与其它玩家下棋!");
             return;
         }
         
          //对方允许游戏
          if (cmds[0].ToUpper() == "JOIN_YES")
         {
             string name = cmds[1];
            
            _PlayerBlack = new Player(ChessColor.Black, name);
            _PlayerBlack.IpAddress = remoteIp;
            
             if (_callBack != null) (_callBack.Target as Form).Invoke(_callBack, "SUCCESS");
            
             //通知对方开始游戏,参数指定(红/黑)玩家先移动棋子.
            SendCommand(_PlayerBlack.IpAddress, "BEGIN:");
            _chessBoard.EnableMove = true; //发起人先移棋子
             this.Play( true);
            
             return;
         }
         
          //对方拒绝玩游戏
          if (cmds[0].ToUpper() == "JOIN_NO")
         {
             if (_callBack != null) _callBack.Invoke("对方拒绝与您玩游戏!");
             return;
         }
         
          #endregion
         
          #region 远程启动游戏命令 (BEGIN)
         
          //接收到远程启动游戏命令
          if (cmds[0].ToUpper() == "BEGIN")
         {
             //如果本地未启动开始,不能玩游戏
             if (!_PlayerRed.Ready) return;
            
             //红黑方都准备就绪
             this.PlayerRed.Ready = true;
             this.PlayerBlack.Ready = true;
            
            _chessBoard.EnableMove = false; //远程玩家后移棋子
             this.Play( false);
             return;
         }
          #endregion
         
          #region 移动棋子
          //移动棋子.参数: MOVE:2,2,5,5
          if (cmds[0].ToUpper() == "MOVE")
         {
             string[] xy = cmds[1].Split( new char[] { char.Parse(",") });
            
            ChessPoint p1 = new ChessPoint( int.Parse(xy[0]), int.Parse(xy[1])); //from pos
            ChessPoint p2 = new ChessPoint( int.Parse(xy[2]), int.Parse(xy[3])); //to pos
            
             //反向坐标,因对方棋子坐标在本机上正好相反.
            p1 = CoordinateHelper.Reverse(p1);
            p2 = CoordinateHelper.Reverse(p2);
            
             //调用远程移动棋子
            _chessBoard.MoveChessByRemote(p1, p2);
             return;
         }
          #endregion
         
          #region 胜利/失败
          //玩家胜利
          if (cmds[0].ToUpper() == "YOU_VICTORY")
         {
            Msg.ShowInformation("您的对手认输,您胜利了!");
             this.Gameover();
             return;
         }
         
          //玩家失败
          if (cmds[0].ToUpper() == "YOU_LOST")
         {
            Msg.ShowInformation("您失败了!");
             this.Gameover();
             return;
         }
          #endregion
      }
      
       //发送命令
       public void SendCommand( string ip, string cmd)
      {
          try
         {
            TcpClient client = new TcpClient();
            client.Connect(IPAddress.Parse(ip), LISTING_PORT);
             if (client.Connected) SendCommand(client.Client, cmd);
         }
          catch
         {
            _PlayerBlack = null;
            Msg.Warning("远程玩家已断线,程序中止!");
             this.Gameover();
         }
      }
      
       public void SendCommand(Socket socket, string cmd)
      {
          if (socket.Connected)
         socket.Send(Encoding.Default.GetBytes(cmd));
      }
      
       /// <summary>
       /// 连接远程玩家电脑
       /// </summary>
       public void ConnectPlayer(ConnectionCallBack callBack, string ip, string player)
      {
          try
         {
            _callBack = callBack;
            TcpClient client = new TcpClient();
            client.Connect(IPAddress.Parse(ip), LISTING_PORT); //连接玩家
            
             if (client.Connected)
            {
                this.SendCommand(client.Client, "JOIN:" + player); //请求连接
                byte[] buffer = new byte[1024];
               client.ReceiveTimeout = 60 * 1000; //等60秒超时
                int i = client.Client.Receive(buffer); //等待远程回复
                if (i > 0)
               {
                   string cmd = Encoding.Default.GetString(buffer).Replace("/0", "");
                  ProcessCommand( null, cmd.Trim()); //处理命令
               }
               client.Close(); //关闭连接
            }
         }
          catch (Exception ex)
         {
            Msg.Warning(ex.Message);
         }
      }
      
       #endregion
      
       /// <summary>
       /// 玩家胜利
       /// </summary>
       public void Victory()
      {
          this.SendCommand(_PlayerBlack.IpAddress, "YOU_LOST:");
          this.Gameover();
      }
      
       /// <summary>
       /// 玩家认输
       /// </summary>
       public void Lost()
      {
          if (_PlayerBlack != null)
          this.SendCommand(_PlayerBlack.IpAddress, "YOU_VICTORY:");
          this.Gameover();
      }
      
       /// <summary>
       /// 游戏结束
       /// </summary>
       public void Gameover()
      {
         _IsPlayGame = false;
         _controlPanel.Reset();
         _chessBoard.Reset(); //画棋盘
         _chessBoard.EnableMove = true;
      }
      
       /// <summary>
       /// 关闭游戏
       /// </summary>
       public void CloseGame()
      {
          this.StopListening();
      }
      
       //获取玩家名称
       public string GetPlayerName()
      {
          string file = Application.StartupPath + "//player.ini";
          if (File.Exists(file))
          return File.ReadAllText(file);
          else
          return Dns.GetHostName(); //取本机电脑名称
      }
      
       /// <summary>
       /// 在左边控制面板上显示最近移动的棋子
       /// </summary>
       /// <param name="chess"></param>
       public void ShowHistory(Chess chess)
      {
         _controlPanel.ShowHistory(chess);
      }
      
       /// <summary>
       /// 向玩家请求悔棋
       /// </summary>
       public void Regret()
      {
          this.SendCommand(_PlayerBlack.IpAddress, "REGRET:");
      }
   }
   
    /// <summary>
    /// 连接远程玩家后回调函数
    /// </summary>
    public delegate void ConnectionCallBack( string backMsg);
   
    public delegate void ControlButtonHandle( bool enable);
   
    public delegate void SetImage(PictureBox control, Image img);
   
    public delegate void SetTimer(System.Windows.Forms.Timer timer, bool enable);
   
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值