本篇将讲的是发到牌以后对手上的牌进行处理。在讲之前,我把本游戏开发要用到的声音 图片下载地址给大家:https://download.csdn.net/download/keepmoving0407/12363899
同时我也刚刚创建了一个QQ学习交流群:1005923608
我们先看一下LoadCards对象类
class LordCards
{
public:
static int getMinSerialLength(int mainNum);
static int getMaxSubNum(int mainNum);
static int getDupSubNum(int mainNum);
static int getCardSuit(int card);
static int getCardValue(int v);
static bool updateHandForNode(OneHand & best, OneHand &left, CardNode & node, bool isTrim);
public:
LordCards(class CardGame * game,int id, const std::vector<int>&vec);
LordCards(class CardGame * game, int id,int cards[], int num);
~LordCards();
LordCards & operator = (const LordCards & other);
void assign(class CardGame * game, const std::vector<int>&vec);
void assign(class CardGame * game, int cards[], int num);
public:
float winRateIfLord();
bool bigEnough();
std::vector<int> removeSubset(const std::vector<int> & subset);
///手牌扫描
int scanToTable();
public:
std::string getKey(bool checkFlower, int &leastValue, int &maxCount);
bool containsFlower(int value, int num);
bool collectNode(CardNode & one, int value, int num);
OneHand calcPowerByRemoveNode(const CardNode & node);
void checkRocket (const std::string & key, OneHand & hand);
void checkBomb4 (const std::string & key, OneHand & hand, int top);
void checkSerial (const std::string & key, OneHand & hand, int top, int mainNum, int len, int subNum);
void checkSub (const std::string & key, OneHand & hand, int mainNum, int subNum, int poss);
OneHand calcPowerValue_noFlower();
OneHand calcPowerValue_expandAny(int countAny, int cardIndex);
OneHand calcPowerValue(bool checkFlower=false);
//打出牌
void playcards(CardNode cards);
CardNode typeAndValueFind();
public:
void collectAllNodes(std::set<CardNode> &possNodes, CardNode & node, int dup);
void sortByFactorInNodes(std::vector<CardNode> &allNodes, const CardNode & other, bool isDirect);
void getGreaterNodes_expandAny(int countAny, int cardIndex, std::set<CardNode> &possNodes, const CardNode &other);
void getGreaterNodes_possNode(std::set<CardNode> &possNodes, const CardNode &other);
std::vector<CardNode> getNodesGreaterThan(const CardNode & node);
//选择最好的出牌
CardNode getBestCardNode(CardNode simple=CardNode());
void getGreaterNodes_simple(std::set<CardNode> &possNodes, const CardNode &other);
int get_GroupData();
public:
class CardGame * theGame;
//位置ID
int id;
CardNode curretCardNode;
std::vector<int> theCards;
//叫地主的倍(1 2 3)
int multiple=-1;
//一共打了几手牌,用于算“春天”
int playTimes=0;
int cardWeight;
void sort();
std::vector<int> m_fillCards[kCard_TableMax];
//kCard_KindMax表示牌的面值大小
//kCard_KindMax
//0数组表示每张牌的数量
//1表示单张序列,顺子 值>4表示顺子
//2表示对子 值>1表示边对
//3三条 值为>1表示飞机
//4炸弹
int cardsTable[kCard_KindMax][kCard_TableMax]; // 保存每牌面值的数目,比如A的牌有几张
};
看了这么多函数,担吓人,这就向通往山顶的阶梯,要一步一步上去!
本篇主要讲 int scanToTable()这个对牌进行扫描分类函数
对牌的种类存储 int cardsTable[kCard_KindMax][kCard_TableMax];
kCard_KindMax的值为5 即0-4
kCard_TableMax的值为30其实只用到了3-17
cardsTable[0][kCard_TableMax]存的是每张牌的个没有就是0 三张就是 3,如cardsTable[0][15]=3表示有三个2,cardsTable[0][16]=1表示有小王cardsTable[0][14]=2表示有2个A
cardsTable[1][kCard_TableMax]存的是否有顺子
cardsTable[2][kCard_TableMax]存的是否有双顺
cardsTable[3][kCard_TableMax]存的是否有飞机
cardsTable[4][kCard_TableMax]存的是否有炸弹
std::vector<int> m_fillCards[kCard_TableMax]数组是对牌的值(1-54)存储
scanToTable()函数:
//对手牌进行扫描
int LordCards::scanToTable(){
//初始化数组为0
memset(cardsTable, 0, sizeof(cardsTable));
//清空数组
for (int i=0; i<kCard_ValueMax; ++i) {
m_fillCards[i].clear();
}
//花牌个数统计 这里没有用到花牌
int countAny = 0;
//对牌到进行从小到大面值排序
std::sort(theCards.begin(), theCards.end(), cardLessThan);
for (int i=0; i<theCards.size(); i++) {
//如果是花牌加1
if (theCards[i] == kCard_Flower) {
++countAny;
continue;
}
int val = LordCards::getCardValue(theCards[i]);//得到一个牌的面值(3-17)
cardsTable[0][val]++;//某张牌个个数加1 如 val=15 那么数组 cardsTable[0][15]=0+1=1 下次再遇到就是再1等于2
m_fillCards[val].push_back(theCards[i]);//这里存的牌的基本值 如黑桃2值为28
}
for (int i = kCard_Value3; i <= kCard_ValueJoker2; ++i)//从3-17循环
{
for (int num = 4; num >= 1; --num)//从四张到单张循环
{
if (cardsTable[0][i] >= num)//如果有这个牌 并且数量为num
{
if (i <= kCard_ValueA)//如果小于等于A
{
//这个是看牌是否连续,比如 cardsTable[num][5]=1
//cardsTable[num][6]是不等于2 cardsTable[num][7]是否等于3 用来判断是否有顺子 双顺 飞机的
cardsTable[num][i] = cardsTable[num][i - 1] + 1;
}
else
{
cardsTable[num][i] = 1;//有一个就是1
}
}
else
{
cardsTable[num][i] = 0;//没有就是0
}
}
}
//这个返回值是花牌的个数 没有用上
return countAny;
}
如下牌
通过scanToTable()后
3,4,5,6,7,8,9,10,J,Q,K,A,2,小,大
"cardsTable[0]的值为:0,0,0,2,2,1,0,1,2,2 ,3, 1,0,1,1,0,0, 1,0,0"//记录了第张牌的数量
"cardsTable[1]的值为:0,0,0,1,2,3,0,1,2,3, 4,5,0,1,2,0,0, 1,0,0" //发现一个顺子(有连续5连):7 8 9 10 J
"cardsTable[2]的值为:0,0,0,1,2,0,0,0,1,2,3,0,0,0,0,0,0,0,0,0"//发现一个双顺( 有对子3连):88 99 10 10
"cardsTable[3]的值为:0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0"//发现一个3条
"cardsTable[4]的值为:0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"
m_fillCards这里存储了每张牌的大值
"数组[0]的值为"
"数组m_fillCards[1]的值为"
"数组m_fillCards[2]的值为"
"数组m_fillCards[3]的值为:16,42"//两个3
"数组m_fillCards[4]的值为:17,30"
"数组m_fillCards[5]的值为:5"
"数组m_fillCards[6]的值为"
"数组m_fillCards[7]的值为:7"
"数组m_fillCards[8]的值为:34,47"
"数组m_fillCards[9]的值为:35,48"
"数组m_fillCards[10]的值为:10,36,49"//三个10
"数组m_fillCards[11]的值为:24"
"数组m_fillCards[12]的值为"
"数组m_fillCards[13]的值为:52"
"数组m_fillCards[14]的值为:40"
"数组m_fillCards[15]的值为"
"数组m_fillCards[16]的值为"
"数组m_fillCards[17]的值为:54"//一个王
"数组m_fillCards[18]的值为"
"数组m_fillCards[19]的值为"
有了牌的这些信息,我们就可以计计算一手牌可以 分几次出,怎样出最花算。本篇就讲这里,下一篇将讲牌的权重,一个牌型的权重是多少?打了这个牌对整个牌的影响力是多少?第一次出哪个牌型最花算等等....