家乡的一种棋牌游戏

进来无事,想起了家乡的一种棋牌游戏,只记得小时候玩觉得蛮有趣,呵呵,现在想起就有一种用程序实现它的冲动,

呵呵,有想法就行动了,鉴于此款游戏由多人组合才能进行,所以还是选择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.youkuaiyun.com/detail/mojiewen2006/4286031 ,后期的修改暂不放上来了,

优快云不让删除,太多了不好

用到的图片如下

 

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.客户端

登陆


登陆后


游戏中


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值