要构建网络版象棋,首先应该创建服务器与客户端,建立socket连接

1) 开局,你是什么颜色

2)选择棋子,

3)走棋

4)悔棋(悔棋悔两步)

5)认输

网络实现:

1)建立连接

a.主机,建立监听socket

b.accept

c.关闭监听socket

a.客户端,连接服务器

2)发送报文

1)服务器给客户端发送开局报文

2)选棋 发送选棋报文

3)走棋 发送走棋报文

4)悔棋

5)认输 重新开始

报文格式定义:

第一个字节表示命令字 0表示开具,1表示选其,2表示走棋,3表示悔棋,4表示认输

开局报文 [0][0或者1] 收到0表示走黑棋,收到1表示走红旗 [0][0] [0][1]

选棋报文 [1][0~31]

走棋报文 [2][0~31][x][y] x和y已经转换好的

悔棋 [3]

认输 [4][0或者1]

运行时设计

定义一个全局变量 char packet[4]用来保存报文

定义一个定时器,每秒去收socket

    #ifndef _Net_H__
#define _Net_H__ #ifdef WIN32
#include <WinSock2.h>
#else
//linux and android #endif // WIN32 class Net
{
public: static SOCKET _server;
static SOCKET _connet; static int _isConnected;
static int _isRecvComplete; static char* _recvData; static bool Listen(short port=9999);
static bool isConnected();
static bool Connect(const char*ip,short port=9999);
static int Send(const char*buffer,int len); //接收数据的接口
static bool RecvStart();
static bool isRecvComplete();
static char *RecvData(int &len); static DWORD WINAPI AcceptThreadFunc(void *arg);
static DWORD WINAPI RecvThreadFunc(void *arg); }; #endif

首先,服务器需要listen函数,一直监听,以得到与客户端的连接

    bool Net::Listen(short port)
{
SOCKET sock=socket(AF_INET,SOCK_STREAM,0);
if (sock==INVALID_SOCKET)
{
return false;
} struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(port);
addr.sin_addr.S_un.S_addr=INADDR_ANY; int ret=bind(sock,(struct sockaddr*)&addr,sizeof(addr));
if (ret != 0)
{
closesocket(sock);
return false;
} listen(sock,10); //10 means listen count //create a therad to accept socket
_server = sock;
_isConnected = 0; HANDLE hThread = CreateThread(NULL, 0, AcceptThreadFunc, NULL, 0, NULL);
CloseHandle(hThread); return true; } DWORD Net::AcceptThreadFunc(void *arg)
{
_connet = accept(_server, NULL, NULL);
_isConnected = 1;
return 0;
}

客户端则需要connect函数与服务器建立连接

    bool Net::Connect(const char*ip,short port)
{ _connet=socket(AF_INET,SOCK_STREAM,0);
if (_connet==INVALID_SOCKET)
{
return false;
} struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.S_un.S_addr = inet_addr(ip); int ret = connect(_connet, (struct sockaddr*)&addr, sizeof(addr));
if (ret != 0)
{
closesocket(_connet);
return false;
} return true; }

如果建立连接成功,则可以互相传递数据了,此时服务器可以关闭连接监听

    void SceneGame::startServer(CCObject*)
{
_bredSide=true;
Net::Listen();
schedule(schedule_selector(SceneGame::CheckListen));
}
void SceneGame::CheckListen(float)
{
if (Net::isConnected())
{
unschedule(schedule_selector(SceneGame::CheckListen));
//game start and do some initiate game
CCLog("server start game\n"); }
}

服务器与客户端互相发送数据,需要send函数

    int Net::Send(const char*buffer,int len)
{
return send(_connet,buffer,len,0);
}

接收数据需要receve函数保持监听

    bool Net::RecvStart()
{
_isRecvComplete=0;
HANDLE hThread=CreateThread(NULL,0,RecvThreadFunc,NULL,0,NULL);
CloseHandle(hThread);
return true;
}
bool Net::isRecvComplete()
{
return _isRecvComplete;
}
char *Net::RecvData(int &len)
{
len=0;
_isRecvComplete=0;
return _recvData;
} DWORD Net::RecvThreadFunc(void *arg)
{
static char buf[16];
recv(_connet,buf,1,0);
if (buf[0]==1)
{
recv(_connet,&buf[1],1,0);
}else if(buf[0]==2)
{
for (int i=1;i<=3;i++)
{
recv(_connet,&buf[i],1,0);
}
} //stop receve
_recvData=buf;
_isRecvComplete=1;
return 0;
}

在象棋中调用发送数据,发送完毕之后轮到对方走了,此时要打开接收数据监听

    //send step
Step* step = *_steps.rbegin();
char buf[4];
buf[0] = 2;
buf[1] = step->moveid;
buf[2] = step->rowTo;
buf[3] = step->colTo;
Net::Send(buf, 4); //receive message
Net::RecvStart();
schedule(schedule_selector(SceneGame::CheckRecv));

接收到数据之后要关闭接收监听,然后开始发送数据,象棋根据传递的报文判断对方的信息,分别以1,2,3开头,表示选择,走棋,其中1与3还需要继续接收数据,2可以关闭数据接收。

    void SceneGame::CheckRecv(float)
{
if (Net::isRecvComplete())
{
unschedule(schedule_selector(SceneGame::CheckRecv));
int len;
char *data=Net::RecvData(len);
//accord to the data protocoal do some work
if (data[0]==1)
{
//selected
_selectid=data[1];
_selectSprite->setPosition(_s[_selectid]->fromPlate());
_selectSprite->setVisible(true); //continue receive
Net::RecvStart();
schedule(schedule_selector(SceneGame::CheckRecv));
}
else if(data[0]==2)
{
//move stone
Stone* s = _s[data[1]];
int row = 9 - data[2];
int col = 8 - data[3];
int killid = getStoneFromRowCol(row, col); recordStep(_selectid, killid, _s[_selectid]->_row, _s[_selectid]->_col, row, col); // 移动棋子
s->_row = row;
s->_col = col;
s->setPosition(s->fromPlate());
if (killid != -1)
{
Stone* ks = _s[killid];
ks->_dead = true;
ks->setVisible(false);
} _selectid = -1;
_selectSprite->setVisible(false);
_bRedTurn = !_bRedTurn;
}else if(data[0]==3)
{
doRegret2();
//continue receive
Net::RecvStart();
schedule(schedule_selector(SceneGame::CheckRecv));
} }
}

windows网络版象棋的实现的更多相关文章

  1. 局域网象棋游戏(C++实现,使用Socket,界面使用Win32,CodeBlocks+GCC编译)

    目录 成果 运行效果图 过程 1. 首先的问题是下棋的两端应该是什么样的? 2. 接下来的问题是怎么表示,怎么存储? 3. 然后应该怎么通信呢? 代码 main.cpp chinese_chess.h ...

  2. 简单的c#winform象棋游戏(附带源码)

    算法源自网络(网络源码连接:http://www.mycodes.net/161/6659.htm)   整体思路:用二维数组构建棋盘每一个数组元素封装为一个picturebox附带若干属性(例如:棋 ...

  3. Windows 7 封装篇(一)【母盘定制】[手动制作]定制合适的系统母盘

    Windows 7 封装篇(一)[母盘定制][手动制作]定制合适的系统母盘 http://www.win10u.com/article/html/10.html Windows 7 封装篇(一)[母盘 ...

  4. DIY_hlstudio_WIN7PE【69M】网络版【89M】

    DIY_hlstudio_WIN7PE[69M]网络版[89M] hlstudio的骨头版PE非常精简,由于启动方式和用法不同,个人进行了如下修改:1.原来的合盘修改为bootmgr直接起动ISO镜像 ...

  5. inno setup判断是Windows系统版本(其实还是Delphi代码,还能检查域控制器和家庭版)

    1.设置Windows最低版本要求 [Setup]: MinVersion 格式: a.bb,c.dd,这里 a.bb 是 Windows 版本,c.dd 是 Windows NT 版本. 默认值: ...

  6. cocos2d-x游戏开发系列教程-中国象棋02-main函数和欢迎页面

    之前两个博客讲述了象棋的规格和工程文件之后,我们继续深入的从代码开始学习cocos2dx 首先从程序入口main函数开始 main函数 int APIENTRY _tWinMain(HINSTANCE ...

  7. Windows Phone开发(5):室内装修

    原文:Windows Phone开发(5):室内装修 为什么叫室内装修呢?呵呵,其实说的是布局,具体些嘛,就是在一个页面中,你如何去摆放你的控件,如何管理它们,你说,像不像我们刚搬进新住所,要&quo ...

  8. JavaScript中国象棋程序(0) - 前言

    “JavaScript中国象棋程序” 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.希望通过这个系列,我们对博弈程序的算法有一定的了解.同时,我们也将构建出一个不错的中国象棋程序 ...

  9. 基于VB中WINSOCK控件的网上象棋系统的实现

    本文发表在<微型机与应用>杂志2001年第3期. 基于VB中WINSOCK控件的网上象棋系统的实现 马根峰1   ,  孙艳2  , 王平1 (1.重庆邮电学院自动化学院,重庆,40006 ...

随机推荐

  1. UVA11584 划分成回文串

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=105116#problem/B 紫书275 题意:输入一个字符,最少能划分几个回文串 分析 ...

  2. POJ3259Wormholes(判断是否存在负回路)

    Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 38300   Accepted: 14095 Descr ...

  3. 菲涅尔反射(Fresnel Reflection)

    离线渲染中,通常可以用kd,ks,kt(分别代表物体的漫反射系数,镜面反射系数,透射系数)来简单地描述一个物体的基本材质,例如,我们将一个物体设置为:kd=0,ks=0.1,kt=0.9,即代表一束光 ...

  4. php排序 sort、rsort、asort、arsort、ksort、krsort

    sort() 函数用于对数组单元从低到高进行排序. rsort() 函数用于对数组单元从高到低进行排序. asort() 函数用于对数组单元从低到高进行排序并保持索引关系. arsort() 函数用于 ...

  5. linux c程序中获取shell脚本输出的实现方法

    linux c程序中获取shell脚本输出的实现方法 1. 前言Unix界有一句名言:“一行shell脚本胜过万行C程序”,虽然这句话有些夸张,但不可否认的是,借助脚本确实能够极大的简化一些编程工作. ...

  6. 关于markdown需要澄清的一些误解

    关于markdown需要澄清的误解: 首先, 最大的一个误解就是 转义! markdown不支持对小于号 < 的转义, 如 \<"pre">, 这时候仍然会认为是 ...

  7. PHP访问数据,增删改

    主页面 <h1>主页面</h1> <table width="100%" border="1" cellpadding=" ...

  8. Windows程序----初识Windows程序

    先来看一些励志名言来激励一下自己吧!  励志名言:每一发奋发奋的背后,必有加倍的赏赐 1.有无目标是成功者与平庸者的根本差别. 2.成功不是将来才有的,而是从决定去做的那一刻起,持续累积而成. 3.当 ...

  9. php面试题之五——MySQL数据库(基础部分)

    五.MySQL数据库 mysql_num_rows() mysql_affected_rows() 这两个函数都作用于 mysql_query($query)操作的结果,mysql_num_rows( ...

  10. Android EditText 文本框实现搜索和清空效果

    前言 本文实现的效果:文本框输入为空时显示输入的图标:不为空时显示清空的图标,此时点击清空图标能清空文本框内输入文字. 声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnbl ...