进来无事,想起了家乡的一种棋牌游戏,只记得小时候玩觉得蛮有趣,呵呵,现在想起就有一种用程序实现它的冲动,
呵呵,有想法就行动了,鉴于此款游戏由多人组合才能进行,所以还是选择C/S结构开发,考虑服务器端会完成多位用
户请求,采用完成端口模型处理服务器端口连接。不多说,首先看游戏玩法规则,如下
1.游戏以 4,5,6,7,8,9,10,J,Q,K,A,2,3,大小王 的顺序分大小,4最小,王最大
2.游戏一开始必须以方块4所得者出牌,且第一次出牌必须打出方块4(可以打出多张4,但方块4必须出)
3.游戏中要是出多张牌的话,只能出同一牌值的牌(如,可以出三个5,但不能出三个5带一张或者一对)
4.要吃上家牌的话,必须要牌值大于上家的,且花色要一样(如果上家除了一个 红心4与梅花4一起,那么必须要大于牌
值的 红心与梅花 例红心5 梅花5 ,或者同牌值的大牌吃,如 黑桃 4与 方块4可以出 花色按 黑桃 红心 梅花 方块
顺序分大小,黑桃最大, 如黑桃4可以吃梅花4)
5.所有出牌都要大于上家牌(除第一次出牌以外),王可以吃任何牌,不需要判断花色,但是出牌的数量要一致,如上家是
出两个 4,那么要用王吃的话也必须出两个王,简单的说就是一个王只能吃一张牌,且大王能吃小王
好了,暂时就想到这么多了,规则大概就这些,开始吧。
关于网络间的通讯采用的是TCP/IP连接,各消息间的传递我采用了枚举来区别,及数据头就是要传达的消息类型,如下枚举
enum msgType{
WS_LOG = 1 , // 登陆
WS_SIT = 2 , // 请求坐下
WS_PLVIEW = 3 , // 用户列表
WS_COMEIN = 4 , // 进入房间
WS_RELLY = 5 , // 准备
WS_OUTROOM = 6 , //离开房间
WS_GAMESTAR = 7 , //开始游戏
WS_GAMECARD = 8 , // 发牌
WS_OUTCARD = 9 , // 出牌
WS_PASSCARD = 10 // 不出
};
程序使用VC6.0开发,服务器端为 win32控制台应用程序(由于没那么多时间去编辑用户窗口,且考虑到控制台程序为效率
最高程序,所以就用它来吧),客户端为win32应用程序,整个游戏过程为几张图片实现,为实现每张牌的显示及大小的判
断,需要专门做一个类,为此我做了如下这么一个类,它可办忙实现了好多功能,呵呵,体积虽然小,但还是有用滴,整
个游戏的关键也还是在牌这个类,其他的就是按部就班的游戏规则了,只要程序按游戏规则走了,那就可以玩了,好了,
做好的东西就先上一下了(由于初步完成而已,其中还有很多需要优化的,后期在来了,起初为了方便测试,没做数据库,
有时间在完成这些步骤了) ;如下连接 http://download.csdn.net/detail/mojiewen2006/4286031 ,后期的修改暂不放上来了,
CSDN不让删除,太多了不好
用到的图片如下
class Card // 牌类
{
public:
Card(){m_select=false;}
void SetPos(int xpos,int ypos) // 设置坐标位置
{
m_xpos=xpos;
m_ypos=ypos;
}
int GetValue(){return m_card;}
bool IsSelect(){return m_select;}
int GetxPos() // 获取x坐标
{
return m_xpos;
}
int GetyPos() // 获取y坐标
{
return m_ypos;
}
int GetxFrame() // 获取图片所在x块
{
return m_xframe;
}
int GetyFrame() // 获取图片所在y块
{
return m_yframe;
}
void Onclick(int xpos,int ypos,bool lastcard=false); // 鼠标单击判断
void IntToPos(int card); // 设置牌值
Card& operator = (const Card& other); //重载=号,用于排序
bool operator< (const Card& other) ; // 重载此运算符只为排序牌值及后面的出牌判断,不做其他用
private:
int m_card; // 牌的数值
int m_xpos; // 牌显示x坐标
int m_ypos; // 牌显示y坐标
bool m_select; // 牌是否被选中,用于出牌判断
int m_xframe; // 对应图片坐标x位置
int m_yframe; // 对应图片坐标y位置
int m_split; // 大小区分
};
如下为它的一些函数
Card& Card::operator = (const Card& other) //重载=号,用于排序
{
m_card=other.m_card; // 牌值
m_xframe=other.m_xframe ; // 对应图片中的x轴块
m_yframe=other.m_yframe ; // 对应图片中的y轴块
m_xpos=other.m_xpos; // 显示的x坐标
m_ypos=other.m_ypos ; // 显示的y坐标
m_select=other.m_select ; // 图片是否被选中
m_split=other.m_split ; // 以什么值分开区别牌的大小
return *this;
}
bool Card::operator< (const Card& other) // 重载此运算符只为排序牌值及后面的出牌判断,不做其他用
{
if(4==m_yframe) // 假如在大猫或小猫一行
{
if(m_yframe==other.m_yframe) // 假如另一张牌也是王
{
if(m_xframe<other.m_xframe )
return true;
else
return false;
}
else // if(m_xframe>other.m_xframe )
{
return false;
}
}
else if(4==other.m_yframe) // 假如第二张牌为王
{
return true;
}
else // 两张牌都不是王
{
if(m_split>=m_xframe) // 从4分开大小
{
if(m_split>=other.m_xframe) // 另一张牌也是在 1,2,3内
{
if(m_xframe<other.m_xframe) // 假如小于
{
return true;
}
else if(m_xframe==other.m_xframe) // 假如牌面相等
{
if(m_yframe<other.m_yframe) // 判断花色
return true ;
else
return false;
}
else // 假如大于
{
return false;
}
}
else if(m_split<other.m_xframe)
{
return false;
}
}
else // 假如牌值不在1,2,3内
{
if(m_split<other.m_xframe) // 另一张牌也不在 1,2,3内
{
if(m_xframe<other.m_xframe) // 假如小于
{
return true;
}
else if(m_xframe==other.m_xframe) // 假如牌面相等
{
if(m_yframe<other.m_yframe) // 判断花色
return true ;
else
return false;
}
else // 假如大于
{
return false;
}
}
else if(m_split>=other.m_xframe) // 另一张牌在1,2,3内
{
return true;
}
}
}
return true;
}
void Card::Onclick(int xpos,int ypos,bool lastcard)
{
if(!lastcard) // 是否最后一张牌,需要特殊处理,此处为不是最后一张牌
{
if(m_select) // 假如选中,开始判断
{
if( (m_xpos<xpos && xpos<(m_xpos + bmCard.GetWidth ()) && m_ypos<ypos && ypos<(m_ypos + CardSpace ) )
|| (m_xpos<xpos && xpos<(m_xpos + CardSpace) && m_ypos < ypos && ypos< (m_ypos + bmCard.GetHeight ()))
)
{
m_xpos=m_xpos;
m_ypos=m_ypos+CardSpace; // 将原来的坐标向下移
m_select=!m_select;
}
}
else // 假如之前未选中
{
if (m_xpos<xpos && xpos<(m_xpos + CardSpace) && m_ypos<ypos && ypos<(m_ypos + bmCard.GetHeight ()) )
{
m_xpos=m_xpos;
m_ypos=m_ypos - CardSpace; // 将原来的坐标向上移
m_select=!m_select;
}
}
}
else // 如果是最后一张牌
{
if(m_select) // 假如选中,开始判断
{
if(m_xpos<xpos && xpos<(m_xpos + bmCard.GetWidth ()) && m_ypos<ypos && ypos<(m_ypos + bmCard.GetHeight () ))
{
m_xpos=m_xpos;
m_ypos=m_ypos+CardSpace; // 将原来的坐标向下移
m_select=!m_select;
}
}
else // 假如之前未选中
{
if (m_xpos<xpos && xpos<(m_xpos + bmCard.GetWidth ()) && m_ypos<ypos && ypos<(m_ypos + bmCard.GetHeight ()) )
{
m_xpos=m_xpos;
m_ypos=m_ypos - CardSpace; // 将原来的坐标向上移
m_select=!m_select;
}
}
}
}
void Card::IntToPos(int card)
{
m_card=card;
m_split=2;
m_xframe=(card-1)%13;
m_yframe=(card-1)/13;
}
程序最终执行结果为
1.服务器
2.客户端
登陆
登陆后
游戏中