中国象棋网络版核心业务类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
{
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; } }
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;
}
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);
}
}
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();
}
}
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);
}
}
}
}
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 移动棋子
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]));
ChessPoint p2 =
new ChessPoint(
int.Parse(xy[2]),
int.Parse(xy[3]));
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));
}
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;
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
public
void Victory()
{
this.SendCommand(_PlayerBlack.IpAddress, "YOU_LOST:");
this.Gameover();
}
public
void Lost()
{
if (_PlayerBlack !=
null)
this.SendCommand(_PlayerBlack.IpAddress, "YOU_VICTORY:");
this.Gameover();
}
public
void Gameover()
{
_IsPlayGame =
false;
_controlPanel.Reset();
_chessBoard.Reset();
_chessBoard.EnableMove =
true;
}
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();
}
public
void ShowHistory(Chess chess)
{
_controlPanel.ShowHistory(chess);
}
public
void Regret()
{
this.SendCommand(_PlayerBlack.IpAddress, "REGRET:");
}
}
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);
}