1 Star 0 Fork 80

wangxy2020 / Landlords

forked from tongshu900220 / Landlords 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
strategy.cpp 20.16 KB
一键复制 编辑 原始数据 按行查看 历史
kevin 提交于 2021-12-16 00:16 . 代码优化, 提高程序的健壮性
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
#include "strategy.h"
#include <QMap>
#include <functional>
Strategy::Strategy(Player *player, const Cards &cards):
m_player(player),
m_cards(cards)
{
}
Cards Strategy::makeStrategy()
{
Player* pendPlayer = m_player->getPendPlayer();
Cards pendCards = m_player->getPendCards();
if(pendPlayer == m_player || pendPlayer == nullptr)
{
return firstPlay();
}
else
{
PlayHand type(pendCards);
Cards beatCards = getGreaterCards(type);
bool shouldBeat = whetherToBeat(beatCards);
if(shouldBeat)
{
return beatCards;
}
else
{
return Cards();
}
}
return Cards();
}
Cards Strategy::firstPlay()
{
PlayHand hand(m_cards);
if(hand.getHandType() != PlayHand::Hand_Unknown)
{
return m_cards;
}
QVector<Cards> optimalSeq = pickOptimalSeqSingles();
if(!optimalSeq.isEmpty())
{
int baseNum = findCardsByCount(1).size();
Cards save = m_cards;
save.remove(optimalSeq);
int lastNum = Strategy(m_player, save).findCardsByCount(1).size();
if(baseNum > lastNum)
{
return optimalSeq[0];
}
}
bool hasPlane, hasTriple, hasPair;
hasPair = hasTriple = hasPlane = false;
Cards backup = m_cards;
QVector<Cards> bombArray = findCardType(PlayHand(PlayHand::Hand_Bomb, Card::Card_Begin, 0), false);
backup.remove(bombArray);
QVector<Cards> planeArray = Strategy(m_player, backup).findCardType(PlayHand(PlayHand::Hand_Plane, Card::Card_Begin, 0), false);
if(!planeArray.isEmpty())
{
hasPlane = true;
backup.remove(planeArray);
}
QVector<Cards> seqTripleArray = Strategy(m_player, backup).findCardType(PlayHand(PlayHand::Hand_Triple, Card::Card_Begin, 0), false);
if(!seqTripleArray.isEmpty())
{
hasTriple = true;
backup.remove(seqTripleArray);
}
QVector<Cards> seqPairArray = Strategy(m_player, backup).findCardType(PlayHand(PlayHand::Hand_Seq_Pair, Card::Card_Begin, 0), false);
if(!seqPairArray.isEmpty())
{
hasPair = true;
backup.remove(seqPairArray);
}
if(hasPair)
{
Cards maxPair;
for(int i=0; i<seqPairArray.size(); ++i)
{
if(seqPairArray[i].cardCount() > maxPair.cardCount())
{
maxPair = seqPairArray[i];
}
}
return maxPair;
}
if(hasPlane)
{
bool twoPairFond = false;
QVector<Cards> pairArray;
for(Card::CardPoint point = Card::Card_3; point <= Card::Card_10; point = Card::CardPoint(point + 1))
{
Cards pair = Strategy(m_player, backup).findSamePointCards(point, 2);
if(!pair.isEmpty())
{
pairArray.push_back(pair);
if(pairArray.size() == 2)
{
twoPairFond = true;
break;
}
}
}
if(twoPairFond)
{
Cards tmp = planeArray[0];
tmp.add(pairArray);
return tmp;
}
else
{
bool twoSingleFond = false;
QVector<Cards> singleArray;
for(Card::CardPoint point = Card::Card_3; point <= Card::Card_10; point = Card::CardPoint(point + 1))
{
if(backup.pointCount(point) == 1)
{
Cards single = Strategy(m_player, backup).findSamePointCards(point, 1);
if(!single.isEmpty())
{
singleArray.push_back(single);
if(singleArray.size() == 2)
{
twoSingleFond = true;
break;
}
}
}
}
if(twoSingleFond)
{
Cards tmp = planeArray[0];
tmp.add(singleArray);
return tmp;
}
else
{
return planeArray[0];
}
}
}
if(hasTriple)
{
if(PlayHand(seqTripleArray[0]).getCardPoint() < Card::Card_A)
{
for(Card::CardPoint point = Card::Card_3; point <= Card::Card_A; point = Card::CardPoint(point+1))
{
int pointCount = backup.pointCount(point);
if(pointCount == 1)
{
Cards single = Strategy(m_player, backup).findSamePointCards(point, 1);
Cards tmp = seqTripleArray[0];
tmp.add(single);
return tmp;
}
else if(pointCount == 2)
{
Cards pair = Strategy(m_player, backup).findSamePointCards(point, 2);
Cards tmp = seqTripleArray[0];
tmp.add(pair);
return tmp;
}
}
}
return seqTripleArray[0];
}
Player* nextPlayer = m_player->getNextPlayer();
if(nextPlayer->getCards().cardCount() == 1 && m_player->getRole() != nextPlayer->getRole())
{
for(Card::CardPoint point = Card::CardPoint(Card::Card_End-1);
point >= Card::Card_3; point = Card::CardPoint(point-1))
{
int pointCount = backup.pointCount(point);
if(pointCount == 1)
{
Cards single = Strategy(m_player, backup).findSamePointCards(point, 1);
return single;
}
else if(pointCount == 2)
{
Cards pair = Strategy(m_player, backup).findSamePointCards(point, 2);
return pair;
}
}
}
else
{
for(Card::CardPoint point = Card::Card_3;
point < Card::Card_End; point = Card::CardPoint(point+1))
{
int pointCount = backup.pointCount(point);
if(pointCount == 1)
{
Cards single = Strategy(m_player, backup).findSamePointCards(point, 1);
return single;
}
else if(pointCount == 2)
{
Cards pair = Strategy(m_player, backup).findSamePointCards(point, 2);
return pair;
}
}
}
return Cards();
}
Cards Strategy::getGreaterCards(PlayHand type)
{
Player* pendPlayer = m_player->getPendPlayer();
if(pendPlayer != nullptr && pendPlayer->getRole() != m_player->getRole() && pendPlayer->getCards().cardCount() <= 3)
{
QVector<Cards> bombs = findCardsByCount(4);
for(int i=0; i<bombs.size(); ++i)
{
if(PlayHand(bombs[i]).canBeat(type))
{
return bombs[i];
}
}
Cards sj = findSamePointCards(Card::Card_SJ, 1);
Cards bj = findSamePointCards(Card::Card_BJ, 1);
if(!sj.isEmpty() && !bj.isEmpty())
{
Cards jokers;
jokers << sj << bj;
return jokers;
}
}
Player* nextPlayer = m_player->getNextPlayer();
Cards remain = m_cards;
remain.remove(Strategy(m_player, remain).pickOptimalSeqSingles());
auto beatCard = std::bind([=](const Cards & cards){
QVector<Cards> beatCardsArray = Strategy(m_player, cards).findCardType(type, true);
if(!beatCardsArray.isEmpty())
{
if(m_player->getRole() != nextPlayer->getRole() && nextPlayer->getCards().cardCount() <= 2)
{
return beatCardsArray.back();
}
else
{
return beatCardsArray.front();
}
}
return Cards();
}, std::placeholders::_1);
Cards cs;
if(!(cs = beatCard(remain)).isEmpty())
{
return cs;
}
else
{
if(!(cs = beatCard(m_cards)).isEmpty()) return cs;
}
return Cards();
}
bool Strategy::whetherToBeat(Cards &cs)
{
if(cs.isEmpty())
{
return false;
}
Player* pendPlayer = m_player->getPendPlayer();
if(m_player->getRole() == pendPlayer->getRole())
{
Cards left = m_cards;
left.remove(cs);
if(PlayHand(left).getHandType() != PlayHand::Hand_Unknown)
{
return true;
}
Card::CardPoint basePoint = PlayHand(cs).getCardPoint();
if(basePoint == Card::Card_2 || basePoint == Card::Card_SJ || basePoint == Card::Card_BJ)
{
return false;
}
}
else
{
PlayHand myHand(cs);
if((myHand.getHandType() == PlayHand::Hand_Triple_Single || myHand.getHandType() == PlayHand::Hand_Triple_Pair)
&& myHand.getCardPoint() == Card::Card_2)
{
return false;
}
if(myHand.getHandType() == PlayHand::Hand_Pair && myHand.getCardPoint() == Card::Card_2
&& pendPlayer->getCards().cardCount() >= 10 && m_player->getCards().cardCount() >= 5)
{
return false;
}
}
return true;
}
Cards Strategy::findSamePointCards(Card::CardPoint point, int count)
{
if(count < 1 || count > 4)
{
return Cards();
}
if(point == Card::Card_SJ || point == Card::Card_BJ)
{
if(count > 1)
{
return Cards();
}
Card card;
card.setPoint(point);
card.setSuit(Card::Suit_Begin);
if(m_cards.contains(card))
{
Cards cards;
cards.add(card);
return cards;
}
return Cards();
}
int findCount = 0;
Cards findCards;
for(int suit = Card::Suit_Begin+1; suit < Card::Suit_End; suit++)
{
Card card;
card.setPoint(point);
card.setSuit((Card::CardSuit)suit);
if(m_cards.contains(card))
{
findCount ++;
findCards.add(card);
if(findCount == count)
{
return findCards;
}
}
}
return Cards();
}
QVector<Cards> Strategy::findCardsByCount(int count)
{
if(count < 1 || count > 4)
{
return QVector<Cards>();
}
QVector<Cards> cardsArray;
for(Card::CardPoint point = Card::Card_3; point < Card::Card_End; point = (Card::CardPoint)(point+1))
{
if(m_cards.pointCount(point) == count)
{
Cards cs;
cs << findSamePointCards(point, count);
cardsArray << cs;
}
}
return cardsArray;
}
Cards Strategy::getRangeCards(Card::CardPoint begin, Card::CardPoint end)
{
Cards rangeCards;
for(Card::CardPoint point = begin; point < end; point = (Card::CardPoint)(point+1))
{
int count = m_cards.pointCount(point);
Cards cs = findSamePointCards(point, count);
rangeCards << cs;
}
return rangeCards;
}
QVector<Cards> Strategy::findCardType(PlayHand hand, bool beat)
{
PlayHand::HandType type = hand.getHandType();
Card::CardPoint point = hand.getCardPoint();
int extra = hand.getExtra();
Card::CardPoint beginPoint = beat ? Card::CardPoint(point + 1) : Card::Card_3;
switch(type)
{
case PlayHand::Hand_Single:
return getCards(beginPoint, 1);
case PlayHand::Hand_Pair:
return getCards(beginPoint, 2);
case PlayHand::Hand_Triple:
return getCards(beginPoint, 3);
case PlayHand::Hand_Triple_Single:
return getTripleSingleOrPair(beginPoint, PlayHand::Hand_Single);
case PlayHand::Hand_Triple_Pair:
return getTripleSingleOrPair(beginPoint, PlayHand::Hand_Pair);
case PlayHand::Hand_Plane:
return getPlane(beginPoint);
case PlayHand::Hand_Plane_Two_Single:
return getPlane2SingleOr2Pair(beginPoint, PlayHand::Hand_Single);
case PlayHand::Hand_Plane_Two_Pair:
return getPlane2SingleOr2Pair(beginPoint, PlayHand::Hand_Pair);
case PlayHand::Hand_Seq_Pair:
{
CardInfo info;
info.begin = beginPoint;
info.end = Card::Card_Q;
info.number = 2;
info.base = 3;
info.extra = extra;
info.beat = beat;
info.getSeq = &Strategy::getBaseSeqPair;
return getSepPairOrSeqSingle(info);
}
case PlayHand::Hand_Seq_Single:
{
CardInfo info;
info.begin = beginPoint;
info.end = Card::Card_10;
info.number = 1;
info.base = 5;
info.extra = extra;
info.beat = beat;
info.getSeq = &Strategy::getBaseSeqSingle;
return getSepPairOrSeqSingle(info);
}
case PlayHand::Hand_Bomb:
return getBomb(beginPoint);
default:
return QVector<Cards>();
}
}
void Strategy::pickSeqSingles(QVector<QVector<Cards>> &allSeqRecord, const QVector<Cards> &seqSingle, const Cards &cards)
{
QVector<Cards> allSeq = Strategy(m_player, cards).findCardType(PlayHand(PlayHand::Hand_Seq_Single, Card::Card_Begin, 0), false);
if(allSeq.isEmpty())
{
allSeqRecord << seqSingle;
}
else
{
Cards saveCards = cards;
for(int i=0; i<allSeq.size(); ++i)
{
Cards aScheme = allSeq.at(i);
Cards temp = saveCards;
temp.remove(aScheme);
QVector<Cards> seqArray = seqSingle;
seqArray << aScheme;
pickSeqSingles(allSeqRecord, seqArray, temp);
}
}
}
QVector<Cards> Strategy::pickOptimalSeqSingles()
{
QVector<QVector<Cards>> seqRecord;
QVector<Cards> seqSingles;
Cards save = m_cards;
save.remove(findCardsByCount(4));
save.remove(findCardsByCount(3));
pickSeqSingles(seqRecord, seqSingles, save);
if(seqRecord.isEmpty())
{
return QVector<Cards>();
}
QMap<int, int> seqMarks;
for(int i=0; i<seqRecord.size(); ++i)
{
Cards backupCards = m_cards;
QVector<Cards> seqArray = seqRecord[i];
backupCards.remove(seqArray);
QVector<Cards> singleArray = Strategy(m_player, backupCards).findCardsByCount(1);
CardList cardList;
for(int j=0; j<singleArray.size(); ++j)
{
cardList << singleArray[j].toCardList();
}
int mark = 0;
for(int j=0; j<cardList.size(); ++j)
{
mark += cardList[j].point() + 15;
}
seqMarks.insert(i, mark);
}
int value = 0;
int comMark = 1000;
auto it = seqMarks.constBegin();
for(;it!=seqMarks.constEnd(); ++it)
{
if(it.value() < comMark)
{
comMark = it.value();
value = it.key();
}
}
return seqRecord[value];
}
QVector<Cards> Strategy::getCards(Card::CardPoint point, int number)
{
QVector<Cards> findCardsArray;
for(Card::CardPoint pt=point; pt < Card::Card_End; pt = (Card::CardPoint)(pt + 1))
{
if(m_cards.pointCount(pt) == number)
{
Cards cs = findSamePointCards(pt, number);
findCardsArray << cs;
}
}
return findCardsArray;
}
QVector<Cards> Strategy::getTripleSingleOrPair(Card::CardPoint begin, PlayHand::HandType type)
{
QVector<Cards> findCardArray = getCards(begin, 3);
if(!findCardArray.isEmpty())
{
Cards remainCards = m_cards;
remainCards.remove(findCardArray);
Strategy st(m_player, remainCards);
QVector<Cards> cardsArray = st.findCardType(PlayHand(type, Card::Card_Begin, 0), false);
if(!cardsArray.isEmpty())
{
for(int i=0; i<findCardArray.size(); ++i)
{
findCardArray[i].add(cardsArray.at(i));
}
}
else
{
findCardArray.clear();
}
}
return findCardArray;
}
QVector<Cards> Strategy::getPlane(Card::CardPoint begin)
{
QVector<Cards> findCardArray;
for(Card::CardPoint point = begin; point <= Card::Card_K; point = (Card::CardPoint)(point+1))
{
Cards prevCards = findSamePointCards(point, 3);
Cards nextCards = findSamePointCards((Card::CardPoint)(point+1), 3);
if(!prevCards.isEmpty() && !nextCards.isEmpty())
{
Cards tmp;
tmp << prevCards << nextCards;
findCardArray << tmp;
}
}
return findCardArray;
}
QVector<Cards> Strategy::getPlane2SingleOr2Pair(Card::CardPoint begin, PlayHand::HandType type)
{
QVector<Cards> findCardArray = getPlane(begin);
if(!findCardArray.isEmpty())
{
Cards remainCards = m_cards;
remainCards.remove(findCardArray);
Strategy st(m_player, remainCards);
QVector<Cards> cardsArray = st.findCardType(PlayHand(type, Card::Card_Begin, 0), false);
if(cardsArray.size() >= 2)
{
for(int i=0; i<findCardArray.size(); ++i)
{
Cards tmp;
tmp << cardsArray[0] << cardsArray[1];
findCardArray[i].add(tmp);
}
}
else
{
findCardArray.clear();
}
}
return findCardArray;
}
QVector<Cards> Strategy::getSepPairOrSeqSingle(CardInfo &info)
{
QVector<Cards> findCardsArray;
if(info.beat)
{
for(Card::CardPoint point = info.begin; point <= info.end; point = (Card::CardPoint)(point+1))
{
bool found = true;
Cards seqCards;
for(int i=0; i<info.extra; ++i)
{
Cards cards = findSamePointCards((Card::CardPoint)(point + i), info.number);
if(cards.isEmpty() || (point + info.extra >= Card::Card_2))
{
found = false;
seqCards.clear();
break;
}
else
{
seqCards << cards;
}
}
if(found)
{
findCardsArray << seqCards;
return findCardsArray;
}
}
}
else
{
for(Card::CardPoint point = info.begin; point <= info.end; point = (Card::CardPoint)(point+1))
{
Cards baseSeq = (this->*info.getSeq)(point);
if(baseSeq.isEmpty())
{
continue;
}
findCardsArray << baseSeq;
int followed = info.base;
Cards alreadyFollowedCards;
while(true)
{
Card::CardPoint followedPoint = Card::CardPoint(point + followed);
if(followedPoint >= Card::Card_2)
{
break;
}
Cards follwedCards = findSamePointCards(followedPoint, info.number);
if(follwedCards.isEmpty())
{
break;
}
else
{
alreadyFollowedCards << follwedCards;
Cards newSeq = baseSeq;
newSeq << alreadyFollowedCards;
findCardsArray << newSeq;
followed++;
}
}
}
}
return findCardsArray;
}
Cards Strategy::getBaseSeqPair(Card::CardPoint point)
{
Cards cards0 = findSamePointCards(point, 2);
Cards cards1 = findSamePointCards((Card::CardPoint)(point+1), 2);
Cards cards2 = findSamePointCards((Card::CardPoint)(point+2), 2);
Cards baseSeq;
if(!cards0.isEmpty() && !cards1.isEmpty() && !cards2.isEmpty())
{
baseSeq << cards0 << cards1 << cards2;
}
return baseSeq;
}
Cards Strategy::getBaseSeqSingle(Card::CardPoint point)
{
Cards cards0 = findSamePointCards(point, 1);
Cards cards1 = findSamePointCards((Card::CardPoint)(point+1), 1);
Cards cards2 = findSamePointCards((Card::CardPoint)(point+2), 1);
Cards cards3 = findSamePointCards((Card::CardPoint)(point+3), 1);
Cards cards4 = findSamePointCards((Card::CardPoint)(point+4), 1);
Cards baseSeq;
if(!cards0.isEmpty() && !cards1.isEmpty() && !cards2.isEmpty() && !cards3.isEmpty() && !cards4.isEmpty())
{
baseSeq << cards0 << cards1 << cards2 << cards3 << cards4;
}
return baseSeq;
}
QVector<Cards> Strategy::getBomb(Card::CardPoint begin)
{
QVector<Cards> findcardsArray;
for(Card::CardPoint point = begin; point < Card::Card_End; point = (Card::CardPoint)(point + 1))
{
Cards cs = findSamePointCards(point, 4);
if(!cs.isEmpty())
{
findcardsArray << cs;
}
}
return findcardsArray;
}
1
https://gitee.com/wangxy202012/landlords.git
git@gitee.com:wangxy202012/landlords.git
wangxy202012
landlords
Landlords
master

搜索帮助