牌型权重

给定一组手牌,怎么计算它的权重呢?我们可以把手牌切分成不同的牌型,一次出牌只能出一个牌型(CardNode),手上有多少个Node就是手数。 我们可以对每种牌型,同一个牌型的每个面值,设置不同的权重。权重可以是正值,也可以是负值。

斗地主以跑牌成功为胜利,手上多一张牌,就多一分负担(。 我们可以考虑以厌恶度来衡量每张牌型的权重。如果出完手上的牌,那么手数为0,权重设为0;以此为基础,面值越小,权重越低,每多一手数就再降低一定的权重。//牌型结构体变量的定义

// 权重计算
#define kOneHandPower (-150) //是每多一手数,就需要降低的权重,
#define kPowerUnit (-100)//是基础厌恶值, 我们通过对不同的牌型,设置不同的bad度,最后得出牌型的权重:
#define kMinPowerValue (-1000000000.0f)//最小权重值

版型CardNode.h头文件:

#define kOneHandPower (-150) //是每多一手数,就需要降低的权重,
#define kPowerUnit (-100)//是基础厌恶值, 我们通过对不同的牌型,设置不同的bad度,最后得出牌型的权重:
#define kMinPowerValue (-1000000000.0f)//最小权重值//合并两个vector
template <typename Ele>
void mergeTwoVectors(std::vector<Ele> & dest, const std::vector<Ele> &src) {dest.insert(dest.end(), src.begin(), src.end());
}//牌型结构体
struct CardNode
{int32_t cardType;//牌型三种: 1 不是连续的牌,包括三条带  ,2 连续的牌 包括顺子  双顺 飞机 , 3 火箭 也就是双王int32_t value ;//牌的值是指单纯类型为牌的面值,连续类型为起始牌的面值,相同牌型以此比较大小;int32_t mainNum; //主牌张数int32_t seralNum;//连续张数int32_t subNum;//副牌张数(三条 四条所带的牌)float aggregate;//权重std::vector<int> cards;//所有的牌
public:CardNode();CardNode(int type, int val, int mainN, int len, int sub);CardNode(const CardNode &other);//赋值CardNode & operator = (const CardNode &other);bool isValidNode() const;//重置为0void resetNode();//获取最大牌值int getTopValue() const;//把版型变为王炸void fillJokers() ;//合并牌型的牌void merge(const CardNode & other);//是否火箭bool isRocket() const;//是否炸弹bool isBomb() const;//比较 是否比Other牌型小bool isExactLessThan(const CardNode & other) const;//比较 是否比Other牌型小bool isStrictLessThan(const CardNode &other) const;//获取牌型的权重float getPower() const;//比较 是否小于bool operator < (const CardNode & other) const;//是否相等bool isEqualTo(const CardNode & other) const;//获取牌的花色和值字符串std::string description() const ;
};

版型CardNode.cpp文件:

CardNode::CardNode() {resetNode();
}CardNode::CardNode(int type, int val, int mainN, int len, int sub) {cardType = type;value = val;mainNum = mainN;seralNum = len;subNum = sub;aggregate = 0.0f;cards.clear();
}CardNode::CardNode(const CardNode &other) {cardType = other.cardType;mainNum = other.mainNum;value = other.value;seralNum = other.seralNum;subNum = other.subNum;aggregate = other.aggregate;cards = other.cards;
}CardNode & CardNode::operator = (const CardNode &other) {cardType = other.cardType;mainNum = other.mainNum;value = other.value;seralNum = other.seralNum;subNum = other.subNum;aggregate = other.aggregate;cards = other.cards;return *this;
}
//是否是一种牌型
bool CardNode::isValidNode() const {return mainNum != 0;
}void CardNode::resetNode() {cardType = 0;value = 0;mainNum = 0;seralNum = 0;subNum = 0;aggregate = 0.0f;cards.clear();
}
//获取最大一张牌的值
int CardNode::getTopValue() const {int top = value;//顺子 或 连对 或飞机if (cardType == kCardType_Serial) {//牌的起始值+连续长度-1top = value + seralNum - 1;}return top;
}//把大小王放到牌中
void CardNode::fillJokers() {cards.clear();if (cardType == kCardType_Rocket) {cards.push_back(kCard_Joker1);cards.push_back(kCard_Joker2);} else {assert(false);}
}
//是否火箭
bool CardNode::isRocket() const {return cardType == kCardType_Rocket;
}bool CardNode::isBomb() const {return (seralNum==1 && mainNum >= 4 && subNum == 0);
}// 比较是否比同一个牌型other小
bool CardNode::isExactLessThan(const CardNode & other) const {if (!isValidNode()) {return true;}return (cardType == other.cardType && mainNum == other.mainNum&& subNum == other.subNum && seralNum == other.seralNum&& getTopValue() < other.getTopValue());
}// 比较炸弹是否比other小
bool CardNode::isStrictLessThan(const CardNode &other) const {if (!isValidNode())return true;if (isRocket()) {//自己是火箭最大return false;}if (other.isRocket()) {//它是火箭,肯定比它小return true;}if (isBomb() && other.isBomb()) {return getTopValue() < other.getTopValue();} else if (isBomb()) {return false;} else if (other.isBomb()) {return true;}return isExactLessThan(other);
}//合并两个型中的牌
void CardNode::merge(const CardNode & other) {mergeTwoVectors(cards, other.cards);
}// 计算当前牌型的权重,全部是预估的;应该用AI来估算会更准确
//会返回每个节点的权重。对于某些大牌,权重为正,剩下的牌型,越厌恶的权重越小
float CardNode::getPower() const {float bad  = 0.0f;//牌型为火箭if (cardType == kCardType_Rocket){bad = -8.0f; // -1.5 * 4.2f}else{//最高值为 牌值大小*2+连续张数 再除以2//假如对2的最高值为(15+15+1)/2=15.5 对3的最高值为: (3+3+1)/2=3.5//334455这样的牌型值为:(3+3+3)/2=4.5float top = ( value + value + seralNum)/2.0f;if (mainNum == 4)//如果为炸弹{if (subNum)//四张带了牌,权重变低{bad = -1.5 * 3.0f + 0.003 * (kCard_Value2 - top) + (seralNum > 1 ? seralNum : 0) * 0.002 - subNum * 0.002;}else if (value == kCard_Value2)//四张2{bad = -1.5f * 3.1f;}else //其它的四张{bad = -1.5f * 4.0f + 0.175 * (kCard_Value2 - top) + (seralNum > 1 ? seralNum : 0) * 0.002;}}else if (mainNum == 3)//三张{bad = 0.433  + 0.02 * (kCard_Value2 - top) + (seralNum > 1 ? seralNum : 0)  * 0.02 - subNum * 0.01;}else if (mainNum == 2) //对子{bad = 0.437  + 0.015 * (kCard_Value2 - top) + (seralNum > 2 ? seralNum : 0) * 0.02;}else  // 单牌{bad = 0.435  + 0.0151 * (kCard_Value2 - top) + (seralNum > 4 ? seralNum : 0) * 0.02;}}float ret = kOneHandPower + kPowerUnit * bad;return ret;
}//比较牌是否比Other小
bool CardNode::operator < (const CardNode & other) const {if (mainNum != other.mainNum) {return mainNum > other.mainNum;}if (value != other.value) {return value < other.value;}if (cardType != other.cardType) {return cardType < other.cardType;}if (seralNum != other.seralNum) {return seralNum < other.seralNum;}if (cards.size() != other.cards.size()) {return cards.size() < other.cards.size();}for (int i=0; i<cards.size(); ++i) {if (cards[i] != other.cards[i]) {return cards[i] < other.cards[i];}}return false;
}
//比较牌是否和Other相等
bool CardNode::isEqualTo(const CardNode & other) const {if (isRocket() && other.isRocket()) {return true;}if (mainNum == other.mainNum && value == other.value&& seralNum == other.seralNum && subNum == other.subNum) {return cards == other.cards;} else {return false;}
}static const char * cardSuits[] = {"♣️", "♦️", "♥️", "♠️"};
static const char * cardValues[] = {"", "1", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A", "2"};
//获取牌的花色和值字符串
std::string CardNode::description() const {std::string ret = "";for (int i=0; i<cards.size(); ++i) {if (cards[i] == kCard_Flower) {ret += "												

C++开发斗地主(QT)第五篇之牌型权重相关推荐

  1. C++开发斗地主(QT)第三篇之动画发牌与位置计算

    本篇讲的是是怎样发牌,计算牌的准确位置,请看下面桌面: 发好牌后的样子: 自己家的牌位置很好计算: 假如牌的大小为122*150,数量为n,每张牌的间隔是40,窗口的宽为width(),高为heigh ...

  2. C++开发斗地主(QT)第一篇之数据结构

    斗地主,是一种在中国流行的纸牌游戏.游戏最少由3个玩家进行,用一副54张牌(连鬼牌),其中一方为地主,其余两家为另一方,双方对战,先出完牌的一方获胜.如今已风靡整个中国,并流行于互联网上! 从今天开始 ...

  3. 斗地主AI算法——第六章の牌型判断

    本章实现了上一章提到的检查当前是否只是一手牌函数ins_SurCardsType /* 检查剩余的牌是否只是一手牌是: 返回手牌类型数据 不是:返回错误类型(cgERROR) */ CardGroup ...

  4. C++开发斗地主(QT)第二篇之牌的绘制与显示

    这一节为什么讲的是牌的显示?因为我觉得要学习这些,必须与实际相结合. 一.单张牌显示控件 (CardWidget) 我的QT版本是5.12.5,编译器是MinGW32,没下载的请先下载QT,下载地址: ...

  5. MFC开发IM-第二十五篇、往MFC编辑框最后面追加文本

    CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT); int nLength = pEdit->GetWindowTextLength(); //选定当前文本 ...

  6. c#开发Mongo笔记第五篇

    现在增删查改算是都完成了,但是查询算是有点不完美的,相信现在用juqeryeasyui这一类的插件的人应该也不少吧,这样的话前台展示需要JSON格式的数据, 好在mogno驱动提供toJson()的函 ...

  7. unity开发 斗地主算法—比较两个手牌的大小

    牌型的定义在http://blog.csdn.net/csdn_cjt/article/details/78593140 第一章 这是第二章 下面是代码 #region isSelectCardCan ...

  8. Android UI开发第三十九篇——Tab界面实现汇总及比较

    Tab布局是iOS的经典布局,Android应用中也有大量应用,前面也写过Android中TAb的实现,<Android UI开发第十八篇--ActivityGroup实现tab功能>.这 ...

  9. 棋牌游戏开发之地主算法判断牌型

    棋牌游戏开发咨询 QQ:325131039 棋牌游戏开发咨询交流群: 490287966 由于近年来网络棋牌游戏的火爆导致个各个地区的特色棋牌游戏进入开发的红火时期,也有越来越多的团队个人开始研究棋牌 ...

  10. Qt笔记(五十四)之Activate控件开发

    一.Activate控件简介(内容摘自自百度) ActiveX控件是Microsoft的ActiveX技术的一部分.ActiveX控件是可以在应用程序和网络中计算机上重复使用的程序对象.创建它的主要技 ...

最新文章

  1. 【Visual Studio 扩展工具】使用ComponentOne中的GroupDefinition和SortDefinition属性保存和还原布局...
  2. 【Android 插件化】使用插件化引擎对应用进行重打包的恶意软件特征 ( 检测困难 | 成本低 | 恶意插件可更换 | 容易传播 )
  3. [Python]小甲鱼Python视频第003课(插曲之变量和字符串)课后题及参考解答
  4. python模块xlwt怎么用不了_python中使用 xlwt 操作excel的常见方法与问题
  5. Oracle数据库表空间占用过大的解决办法
  6. EF三种编程方式详细图文教程(C#+EF)之Database First
  7. dubbo admin默认端口_Dubbo学习(四) Dubbo 从下载到编译成功
  8. 利用python模拟菜刀反弹shell绕过限制
  9. 洛谷P1073 最优贸易
  10. MS SQL 监控数据/日志文件增长
  11. GIT 学习笔记 - 20181201
  12. html如何实现字体逐个输入,HTML – 如何将字体真棒图标插入文本输入?
  13. ImportError: No module named 'ConfigParser'和ImportError: No module named 'cPickle'
  14. webgis之qgis缓存
  15. Centos7安装源地址
  16. pkl文件与pickle.dump,pickle.load
  17. HTTPS数字证书原理
  18. PTA:设计一个风扇Fan类 (20 分)
  19. 三次曲线和五次曲线函数
  20. python的六种基本数据类型_Python基本数据类型

热门文章

  1. 联想服务器bios中文显示,联想bios怎么设置中文显示
  2. The Tangled Web: A Guide to Securing Modern Web Applications 原版pdf
  3. esp32语音播放天气预报
  4. ankhsvn vs2017 64位下载 v2.7.12815
  5. python绘制网格地图_「GIS教程」Python-GeoPandas地图、专题地图绘制
  6. 格式化U盘并测试读写速度
  7. C++ Opencv 安装配置
  8. MD5加密----------
  9. 自媒体短视频怎么制作?视频制作大神分享的超全教程,新手也能轻松上手!
  10. NPDP认证怎么考?有用吗?