x01.Weiqi.3 网络对弈

为简化,只实现了两个用户的网络对弈。但在此基础上,即使去实现一个具有商业价值的网络对弈程序,应该也不是什么难事。毕竟,核心的问题已经解决了。
首先,是服务端。新建一个 WinForm 项目 Server。在主窗口中,添加一个按钮m_ButtonStartServer,双击,在 click 事件中,实现TcpListener 的诸多功能。
主窗口文件 MainForm.cs 内容如下:
MainForm
namespace Server
{
publicpartialclass MainForm : Form
{
TcpListener m_TcpListener;
List
<User> m_Users =new List<User>(); //为简化,只作 2 想

public MainForm()
{
InitializeComponent();
}

privatevoid ButtonStartServer_Click(object sender, EventArgs e)
{
IPAddress ip
= Dns.GetHostAddresses(Dns.GetHostName())[0];
m_TcpListener
=new TcpListener(ip, 51000);
m_TcpListener.Start();

ThreadStart threadStart
=new ThreadStart(ListenClient);
Thread thread
=new Thread(threadStart);
thread.Start();

MessageBox.Show(
"Start server success!");
}

void ListenClient()
{
while (true)
{
TcpClient client
=null;
try
{
client
= m_TcpListener.AcceptTcpClient();
}
catch
{
break; // 以此退出?
}
User user
=new User(client);
m_Users.Add(user);

ParameterizedThreadStart ptStart
=new ParameterizedThreadStart(ReceiveData);
Thread thread
=new Thread(ptStart);
thread.Start(user);
}
}

void ReceiveData(object u)
{
User user
= (User)u;
while (true)
{
string data = user.Reader.ReadLine();
for (int i =0; i <2; i++)
{
string color = i %2==0?"black" : "white";
m_Users[i].Writer.WriteLine(
string.Format("{0},{1}", color, data));
m_Users[i].Writer.Flush();
}
}
}

protectedoverridevoid OnClosing(CancelEventArgs e)
{
base.OnClosing(e);

foreach (var item in m_Users)
{
item.Client.Close();
}
m_TcpListener.Stop();
}
}
}
其中,User 是为方便用户管理而添加的类。
代码文件 User.cs 内容如下:
User
namespace Server
{
class User
{
public TcpClient Client { get; privateset; }
public StreamReader Reader { get; privateset; }
public StreamWriter Writer { get; privateset; }
public User(TcpClient client)
{
this.Client = client;
NetworkStream netStream
= client.GetStream();
Reader
=new StreamReader(netStream, System.Text.Encoding.UTF8);
Writer
=new StreamWriter(netStream, System.Text.Encoding.UTF8);
}
}
}
如此,服务端就算完成。
客户端,直接从 BoardBase 继承,类名为:InetBoard。
代码文件 InetBoard.cs 内容如下:
InetBoard
namespace x01.Weiqi.Board
{
publicclass InetBoard : BoardBase
{
int m_Col =-1, m_Row =-1, m_StepCount =-1;
string m_Color =string.Empty;
TcpClient m_Client
=null;
StreamWriter m_Writer
=null;
StreamReader m_Reader
=null;
int m_Count =0;
System.Windows.Forms.Timer m_Timer
=new System.Windows.Forms.Timer();

public InetBoard(int size =38)
:
base(size)
{
m_Timer.Tick
+=new EventHandler(Timer_Tick);
m_Timer.Start();

InitClient();
}

void Timer_Tick(object sender, EventArgs e)
{
Draw();
}

void Draw()
{
int col = m_Col;
int row = m_Row;
if (NotIn(col, row))
{
return;
}
DrawChess(col, row);
Eat(col, row);

m_Count
++;
}

void InitClient()
{
// 测试,取主机即可。实际,应为服务器域名
m_Client =new TcpClient(Dns.GetHostName(), 51000);
m_Writer
=new StreamWriter(m_Client.GetStream(), Encoding.UTF8);
m_Reader
=new StreamReader(m_Client.GetStream(), Encoding.UTF8);

Thread thread
=new Thread(new ThreadStart(Receive));
thread.Start();
}

void Receive()
{
while (true)
{
string data = m_Reader.ReadLine();
string[] step = data.Split(',');
m_Color
= step[0];
m_Col
=int.Parse(step[1]);
m_Row
=int.Parse(step[2]);
m_StepCount
=int.Parse(step[3]);
}
}

void Send(string data)
{
m_Writer.WriteLine(data);
m_Writer.Flush();
}

protectedoverridevoid OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);

if (m_Color =="black"&& IsBlack !=false)
{
return;
}

if (m_Color =="white"&& IsBlack ==false)
{
return;
}

int col = (int)e.GetPosition(this).X / ChessSize;
int row = (int)e.GetPosition(this).Y / ChessSize;

string data =string.Format("{0},{1},{2}", col, row, m_Count +1);
Send(data);
}
}
}
用户控件 Chess 只能在 STA 中处理,故添加了一个 Timer。逻辑不复杂,不详叙。
用法:
1. 运行Server,效果图如下:
2. 启动两个 x01.Weiqi,从菜单中选择 Inet 项。用户1和2的运行效果图如下:

源代码可从 http://www.cnblogs.com/china_x01  的 download\code\x01.Weiqi 获取。

Copyright (c) 2011 by x01(china_x01@qq.com),未经许可,请勿转载。

posted on 2011-05-17 12:13  x01  阅读(1438)  评论(3编辑  收藏  举报

导航