斗地主后1055行(c++11及以上)
2025-07-18 23:01:17
发布于:福建
break;
default:
break;
}
return group;
}
// 跟单牌策略优化:中期避免使用大牌
CardGroup tryFollowSingle(const CardGroup& lastGroup, const GameState& state, bool conservative) {
CardGroup group;
vector<Card> candidates;
for (const Card& card : hand) {
if (card.rank > lastGroup.mainRank) {
candidates.push_back(card);
}
}
if (candidates.empty()) {
return group;
}
// 关键改进:避免使用关键牌压制队友
if (!isLandlord && state.landlordPosition == lastGroup.player) {
// 对手出牌,可以适当压制
} else if (!isLandlord) {
// 队友出牌,避免用关键牌压制
vector<Card> nonCriticalCandidates;
for (const Card& c : candidates) {
if (!isCriticalCard(c.rank)) {
nonCriticalCandidates.push_back(c);
}
}
if (!nonCriticalCandidates.empty()) {
candidates = nonCriticalCandidates;
}
}
if (isMidGame()) {
vector<Card> mediumCards;
for (const Card& c : candidates) {
if (!isHighValueCard(c.rank)) {
mediumCards.push_back(c);
}
}
if (!mediumCards.empty()) {
sort(mediumCards.begin(), mediumCards.end(), [](const Card& a, const Card& b) {
return a.rank < b.rank;
});
group.cards.push_back(mediumCards[0]);
group.type = CardType::SINGLE;
group.mainRank = mediumCards[0].rank;
return group;
}
}
if (conservative) {
sort(candidates.begin(), candidates.end(), [](const Card& a, const Card& b) {
return a.rank < b.rank;
});
group.cards.push_back(candidates[0]);
} else {
sort(candidates.begin(), candidates.end(), [](const Card& a, const Card& b) {
return a.rank > b.rank;
});
group.cards.push_back(candidates.back());
if (!isLandlord && state.landlordPosition == lastGroup.player) {
if (lastGroup.mainRank < Card::TEN) {
for (const Card& c : candidates) {
if (c.rank <= lastGroup.mainRank + 2 && c.rank > lastGroup.mainRank) {
group.cards[0] = c;
break;
}
}
}
}
}
group.type = CardType::SINGLE;
group.mainRank = group.cards[0].rank;
return group;
}
// 跟对子策略优化:中期避免使用大牌
CardGroup tryFollowPair(const CardGroup& lastGroup, const GameState& state, bool conservative) {
CardGroup group;
map<Card::Rank, int> rankCount = getRankCount();
Card::Rank bestRank = Card::B_JOKER;
bool found = false;
// 关键改进:避免使用关键牌压制队友
bool avoidCritical = !isLandlord && (state.landlordPosition != lastGroup.player);
for (const auto& entry : rankCount) {
if (entry.second >= 2 && entry.first > lastGroup.mainRank) {
if (avoidCritical && isCriticalCard(entry.first)) {
continue; // 跳过关键牌
}
if (isMidGame() && isHighValueCard(entry.first)) {
continue;
}
if (conservative) {
if (entry.first < bestRank) {
bestRank = entry.first;
found = true;
}
} else {
if (!found || entry.first < bestRank) {
bestRank = entry.first;
found = true;
}
}
}
}
if (!found && !isLandlord && state.landlordPosition == lastGroup.player) {
if (lastGroup.mainRank < Card::TEN) {
for (const auto& entry : rankCount) {
if (entry.second >= 2 && entry.first > lastGroup.mainRank &&
entry.first <= lastGroup.mainRank + 2 &&
!isHighValueCard(entry.first)) {
bestRank = entry.first;
found = true;
break;
}
}
}
}
if (found) {
int count = 0;
for (const Card& c : hand) {
if (c.rank == bestRank) {
group.cards.push_back(c);
count++;
if (count == 2) break;
}
}
group.type = CardType::PAIR;
group.mainRank = bestRank;
}
return group;
}
// 跟三张策略优化:中期避免使用大牌
CardGroup tryFollowTriplet(const CardGroup& lastGroup, const GameState& state, bool conservative) {
CardGroup group;
map<Card::Rank, int> rankCount = getRankCount();
Card::Rank bestRank = Card::B_JOKER;
bool found = false;
// 关键改进:避免使用关键牌压制队友
bool avoidCritical = !isLandlord && (state.landlordPosition != lastGroup.player);
for (const auto& entry : rankCount) {
if (entry.second >= 3 && entry.first > lastGroup.mainRank) {
if (avoidCritical && isCriticalCard(entry.first)) {
continue; // 跳过关键牌
}
if (isMidGame() && isHighValueCard(entry.first)) {
continue;
}
if (conservative) {
if (entry.first < bestRank) {
bestRank = entry.first;
found = true;
}
} else {
if (!found || entry.first < bestRank) {
bestRank = entry.first;
found = true;
}
}
}
}
if (found) {
int count = 0;
for (const Card& c : hand) {
if (c.rank == bestRank) {
group.cards.push_back(c);
count++;
if (count == 3) break;
}
}
group.type = CardType::TRIPLET;
group.mainRank = bestRank;
}
return group;
}
CardGroup tryFollowStraight(const CardGroup& lastGroup, const GameState& state) {
if (lastGroup.length <= 0) {
return CardGroup();
}
CardGroup group;
int length = lastGroup.length;
vector<int> ranks;
for (const Card& card : hand) {
if (card.suit != Card::JOKER && card.rank < Card::TWO) {
ranks.push_back(card.rank);
}
}
sort(ranks.begin(), ranks.end());
auto last = unique(ranks.begin(), ranks.end());
ranks.erase(last, ranks.end());
for (int start = 0; start <= (int)ranks.size() - length; start++) {
bool valid = true;
int endRank = ranks[start] + length - 1;
for (int i = 0; i < length; i++) {
if (ranks[start + i] != ranks[start] + i) {
valid = false;
break;
}
}
if (valid && endRank > lastGroup.mainRank) {
for (int i = 0; i < length; i++) {
for (const Card& c : hand) {
if (c.rank == ranks[start + i]) {
group.cards.push_back(c);
break;
}
}
}
group.type = CardType::STRAIGHT;
group.mainRank = endRank;
group.length = length;
return group;
}
}
return group;
}
CardGroup tryFollowStraightPairs(const CardGroup& lastGroup, const GameState& state) {
if (lastGroup.length <= 0) {
return CardGroup();
}
CardGroup group;
int pairCount = lastGroup.length;
int requiredLength = pairCount * 2;
map<Card::Rank, int> rankCount = getRankCount();
vector<Card::Rank> availableRanks;
for (const auto& entry : rankCount) {
if (entry.second >= 2 && entry.first < Card::TWO) {
availableRanks.push_back(entry.first);
}
}
sort(availableRanks.begin(), availableRanks.end());
if (availableRanks.size() < pairCount) {
return group;
}
for (int start = 0; start <= (int)availableRanks.size() - pairCount; start++) {
bool valid = true;
Card::Rank endRank = static_cast<Card::Rank>(availableRanks[start] + pairCount - 1);
for (int i = 0; i < pairCount; i++) {
if (availableRanks[start + i] != availableRanks[start] + i) {
valid = false;
break;
}
}
if (valid && endRank > lastGroup.mainRank) {
for (int i = 0; i < pairCount; i++) {
Card::Rank rank = availableRanks[start + i];
int count = 0;
for (const Card& c : hand) {
if (c.rank == rank) {
group.cards.push_back(c);
count++;
if (count == 2) break;
}
}
}
group.type = CardType::STRAIGHT_PAIRS;
group.mainRank = endRank;
group.length = pairCount;
return group;
}
}
return group;
}
CardGroup tryFollowPlane(const CardGroup& lastGroup, const GameState& state) {
if (lastGroup.length <= 0) {
return CardGroup();
}
CardGroup group;
int tripletCount = lastGroup.length;
bool withSingles = (lastGroup.type == CardType::PLANE_WITH_SINGLES);
bool withPairs = (lastGroup.type == CardType::PLANE_WITH_PAIRS);
map<Card::Rank, int> rankCount = getRankCount();
vector<Card::Rank> availableRanks;
for (const auto& entry : rankCount) {
if (entry.second >= 3 && entry.first < Card::TWO) {
availableRanks.push_back(entry.first);
}
}
sort(availableRanks.begin(), availableRanks.end());
if (availableRanks.size() < tripletCount) {
return group;
}
for (int start = 0; start <= (int)availableRanks.size() - tripletCount; start++) {
bool valid = true;
Card::Rank endRank = static_cast<Card::Rank>(availableRanks[start] + tripletCount - 1);
for (int i = 0; i < tripletCount; i++) {
if (availableRanks[start + i] != availableRanks[start] + i) {
valid = false;
break;
}
}
if (valid && endRank > lastGroup.mainRank) {
for (int i = 0; i < tripletCount; i++) {
Card::Rank rank = availableRanks[start + i];
int count = 0;
for (const Card& c : hand) {
if (c.rank == rank) {
group.cards.push_back(c);
count++;
if (count == 3) break;
}
}
}
if (withSingles || withPairs) {
vector<Card> extraCards;
for (const Card& c : hand) {
bool isTripletCard = false;
for (int i = 0; i < tripletCount; i++) {
if (c.rank == availableRanks[start + i]) {
isTripletCard = true;
break;
}
}
if (!isTripletCard) {
extraCards.push_back(c);
}
}
int extraNeeded = tripletCount * (withPairs ? 2 : 1);
if (extraCards.size() >= extraNeeded) {
sort(extraCards.begin(), extraCards.end());
if (withPairs) {
map<Card::Rank, int> pairCount;
vector<Card> pairs;
for (const Card& c : extraCards) {
if (pairCount[c.rank] < 2) {
pairs.push_back(c);
pairCount[c.rank]++;
}
}
if (pairs.size() >= extraNeeded) {
for (int i = 0; i < extraNeeded; i++) {
group.cards.push_back(pairs[i]);
}
} else {
group.cards.clear();
continue;
}
} else {
for (int i = 0; i < extraNeeded; i++) {
group.cards.push_back(extraCards[i]);
}
}
group.type = withPairs ? CardType::PLANE_WITH_PAIRS : CardType::PLANE_WITH_SINGLES;
group.mainRank = endRank;
group.length = tripletCount;
return group;
}
} else {
group.type = CardType::PLANE;
group.mainRank = endRank;
group.length = tripletCount;
return group;
}
}
}
return group;
}
CardGroup tryFollowTripletWithSingle(const CardGroup& lastGroup, const GameState& state) {
CardGroup group;
map<Card::Rank, int> rankCount = getRankCount();
Card::Rank bestRank = Card::B_JOKER;
bool found = false;
// 关键改进:避免使用关键牌压制队友
bool avoidCritical = !isLandlord && (state.landlordPosition != lastGroup.player);
for (const auto& entry : rankCount) {
if (entry.second >= 3 && entry.first > lastGroup.mainRank) {
if (avoidCritical && isCriticalCard(entry.first)) {
continue; // 跳过关键牌
}
if (isMidGame() && isHighValueCard(entry.first)) {
continue;
}
bestRank = entry.first;
found = true;
break;
}
}
if (!found) {
return group;
}
int count = 0;
for (const Card& c : hand) {
if (c.rank == bestRank) {
group.cards.push_back(c);
count++;
if (count == 3) break;
}
}
Card::Rank singleRank = Card::B_JOKER;
for (const auto& entry : rankCount) {
if (entry.first != bestRank && entry.first < singleRank) {
singleRank = entry.first;
}
}
if (singleRank != Card::B_JOKER) {
for (const Card& c : hand) {
if (c.rank == singleRank) {
group.cards.push_back(c);
break;
}
}
group.type = CardType::TRIPLET_WITH_SINGLE;
group.mainRank = bestRank;
return group;
}
return group;
}
CardGroup tryFollowTripletWithPair(const CardGroup& lastGroup, const GameState& state) {
CardGroup group;
map<Card::Rank, int> rankCount = getRankCount();
Card::Rank bestRank = Card::B_JOKER;
bool found = false;
// 关键改进:避免使用关键牌压制队友
bool avoidCritical = !isLandlord && (state.landlordPosition != lastGroup.player);
for (const auto& entry : rankCount) {
if (entry.second >= 3 && entry.first > lastGroup.mainRank) {
if (avoidCritical && isCriticalCard(entry.first)) {
continue; // 跳过关键牌
}
if (isMidGame() && isHighValueCard(entry.first)) {
continue;
}
bestRank = entry.first;
found = true;
break;
}
}
if (!found) {
return group;
}
int count = 0;
for (const Card& c : hand) {
if (c.rank == bestRank) {
group.cards.push_back(c);
count++;
if (count == 3) break;
}
}
Card::Rank pairRank = Card::B_JOKER;
for (const auto& entry : rankCount) {
if (entry.first != bestRank && entry.second >= 2 && entry.first < pairRank) {
pairRank = entry.first;
}
}
if (pairRank != Card::B_JOKER) {
count = 0;
for (const Card& c : hand) {
if (c.rank == pairRank) {
group.cards.push_back(c);
count++;
if (count == 2) break;
}
}
group.type = CardType::TRIPLET_WITH_PAIR;
group.mainRank = bestRank;
return group;
}
return group;
}
CardGroup tryFollowFourWithTwo(const CardGroup& lastGroup, const GameState& state) {
CardGroup group;
map<Card::Rank, int> rankCount = getRankCount();
Card::Rank bestRank = Card::B_JOKER;
bool found = false;
// 关键改进:避免使用关键牌压制队友
bool avoidCritical = !isLandlord && (state.landlordPosition != lastGroup.player);
for (const auto& entry : rankCount) {
if (entry.second == 4 && entry.first > lastGroup.mainRank) {
if (avoidCritical && isCriticalCard(entry.first)) {
continue; // 跳过关键牌
}
if (isMidGame() && isHighValueCard(entry.first)) {
continue;
}
bestRank = entry.first;
found = true;
break;
}
}
if (!found) {
return group;
}
int count = 0;
for (const Card& c : hand) {
if (c.rank == bestRank) {
group.cards.push_back(c);
count++;
if (count == 4) break;
}
}
vector<Card> singles;
for (const Card& c : hand) {
if (c.rank != bestRank) {
singles.push_back(c);
if (singles.size() == 2) break;
}
}
if (singles.size() == 2) {
group.cards.insert(group.cards.end(), singles.begin(), singles.end());
group.type = CardType::FOUR_WITH_TWO;
group.mainRank = bestRank;
return group;
}
return group;
}
CardGroup tryPlayStraightPairs() {
CardGroup group;
map<Card::Rank, int> rankCount = getRankCount();
vector<Card::Rank> availableRanks;
for (const auto& entry : rankCount) {
if (entry.second >= 2 && entry.first < Card::TWO) {
availableRanks.push_back(entry.first);
}
}
sort(availableRanks.begin(), availableRanks.end());
if (availableRanks.size() < 3) {
return group;
}
int maxLength = 0;
int bestStart = 0;
int currentLength = 1;
for (int i = 1; i < availableRanks.size(); i++) {
if (availableRanks[i] == availableRanks[i-1] + 1) {
currentLength++;
if (currentLength > maxLength) {
maxLength = currentLength;
bestStart = i - currentLength + 1;
}
} else {
currentLength = 1;
}
}
if (maxLength >= 3) {
for (int i = 0; i < maxLength; i++) {
Card::Rank rank = availableRanks[bestStart + i];
int count = 0;
for (const Card& c : hand) {
if (c.rank == rank) {
group.cards.push_back(c);
count++;
if (count == 2) break;
}
}
}
group.type = CardType::STRAIGHT_PAIRS;
group.mainRank = availableRanks[bestStart + maxLength - 1];
group.length = maxLength;
}
return group;
}
CardGroup tryPlayStraight() {
CardGroup group;
vector<int> ranks;
for (const Card& card : hand) {
if (card.suit != Card::JOKER && card.rank < Card::TWO) {
ranks.push_back(card.rank);
}
}
sort(ranks.begin(), ranks.end());
auto last = unique(ranks.begin(), ranks.end());
ranks.erase(last, ranks.end());
if (ranks.size() < 5) {
return group;
}
int maxLength = 1;
int currentLength = 1;
int bestStart = 0;
for (int i = 1; i < ranks.size(); i++) {
if (ranks[i] == ranks[i-1] + 1) {
currentLength++;
if (currentLength > maxLength) {
maxLength = currentLength;
bestStart = i - currentLength + 1;
}
} else {
currentLength = 1;
}
}
if (maxLength >= 5) {
for (int i = 0; i < maxLength; i++) {
for (const Card& c : hand) {
if (c.rank == ranks[bestStart + i]) {
group.cards.push_back(c);
break;
}
}
}
group.type = CardType::STRAIGHT;
group.mainRank = ranks[bestStart + maxLength - 1];
group.length = maxLength;
}
return group;
}
CardGroup tryPlaySmallPair() {
CardGroup group;
map<Card::Rank, int> rankCount = getRankCount();
Card::Rank minPairRank = Card::B_JOKER;
for (const auto& entry : rankCount) {
if (entry.second >= 2 && entry.first < minPairRank &&
!isHighValueCard(entry.first)) {
minPairRank = entry.first;
}
}
if (minPairRank != Card::B_JOKER) {
int count = 0;
for (const Card& c : hand) {
if (c.rank == minPairRank) {
group.cards.push_back(c);
count++;
if (count == 2) break;
}
}
group.type = CardType::PAIR;
group.mainRank = minPairRank;
}
return group;
}
CardGroup tryPlayBomb() {
CardGroup group;
if (hasRocket()) {
for (const Card& card : hand) {
if (card.suit == Card::JOKER) {
group.cards.push_back(card);
if (group.cards.size() == 2) break;
}
}
group.type = CardType::ROCKET;
group.mainRank = Card::B_JOKER;
return group;
}
map<Card::Rank, int> rankCount = getRankCount();
for (const auto& entry : rankCount) {
if (entry.second == 4) {
for (const Card& c : hand) {
if (c.rank == entry.first) {
group.cards.push_back(c);
}
}
group.type = CardType::BOMB;
group.mainRank = entry.first;
return group;
}
}
return group;
}
};
// 游戏类
class DouDiZhuGame {
private:
vector<Card> deck;
vector<Player*> players;
int landlordIndex = -1;
vector<Card> landlordCards;
int currentPlayer = 0;
int passCount = 0;
CardGroup lastGroup;
bool gameEnded = false;
int winner = -1;
GameState gameState;
bool enableTracker = false;
void createDeck() {
deck.clear();
int idCounter = 0;
for (int s = Card::HEART; s <= Card::SPADE; s++) {
for (int r = Card::THREE; r <= Card::TWO; r++) {
deck.push_back(Card(static_cast<Card::Suit>(s),
static_cast<Card::Rank>(r),
idCounter++));
}
}
deck.push_back(Card(Card::JOKER, Card::L_JOKER, idCounter++));
deck.push_back(Card(Card::JOKER, Card::B_JOKER, idCounter++));
}
void shuffleDeck() {
random_device rd;
mt19937 g(rd());
shuffle(deck.begin(), deck.end(), g);
}
void dealCards() {
for (int i = 0; i < 51; i++) {
players[i % 3]->hand.push_back(deck[i]);
}
landlordCards = vector<Card>(deck.begin() + 51, deck.end());
for (Player* p : players) {
p->sortHand();
}
}
void callLandlord() {
int maxBid = 0;
int lastBidder = -1;
cout << "\n===== 叫地主阶段 =====\n";
for (int round = 0; round < 3; round++) {
bool bidMade = false;
for (int i = 0; i < 3; i++) {
int bid = players[i]->callLandlord(maxBid);
if (bid > maxBid) {
lastBidder = i;
maxBid = bid;
bidMade = true;
gameState.bidScore = maxBid;
}
}
if (maxBid == 3) {
break;
}
if (!bidMade) {
break;
}
}
if (lastBidder != -1) {
landlordIndex = lastBidder;
players[landlordIndex]->isLandlord = true;
gameState.landlordPosition = landlordIndex;
players[landlordIndex]->addCards(landlordCards);
cout << "\n=== " << players[landlordIndex]->name << " 成为地主! (叫分:" << maxBid << ") ===\n";
cout << "底牌: ";
for (const Card& c : landlordCards) {
cout << c.toString() << " ";
}
cout << endl;
currentPlayer = landlordIndex;
gameState.landlordRemainingCards = players[landlordIndex]->hand.size();
} else {
cout << "无人叫地主,重新发牌..." << endl;
resetGame();
startGame();
}
}
void playTurn() {
Player* current = players[currentPlayer];
cout << "\n当前玩家: " << current->name;
if (current->isLandlord) cout << " (地主)";
cout << endl;
// 更新玩家手牌数量
for (int i = 0; i < 3; i++) {
gameState.playerCardCount[i] = players[i]->hand.size();
}
// 更新地主剩余牌数
if (current->isLandlord) {
gameState.landlordRemainingCards = current->hand.size();
}
else {
// 非地主玩家也要更新地主牌数(如果地主是其他玩家)
if (players[landlordIndex]->isLandlord) {
gameState.landlordRemainingCards = players[landlordIndex]->hand.size();
}
}
gameState.checkEndgame();
CardGroup group = current->playCard(lastGroup, gameState);
if (group.type != CardType::ILLEGAL) {
lastGroup = group;
lastGroup.player = currentPlayer;
passCount = 0;
gameState.lastPlayedPlayer = currentPlayer;
for (Player* p : players) {
p->updateTracker(currentPlayer, group.cards);
}
cout << current->name << " 出牌: ";
for (const Card& card : group.cards) {
cout << card.toString() << " ";
}
cout << " (牌型: " << cardTypeToString(group.type) << ")" << endl;
current->removeCards(group.cards);
if (current->hand.empty()) {
gameEnded = true;
winner = currentPlayer;
}
} else {
cout << current->name << " 选择跳过" << endl;
passCount++;
if (passCount == 2) {
lastGroup = CardGroup();
passCount = 0;
cout << "连续两个玩家跳过,牌局重置" << endl;
}
}
currentPlayer = (currentPlayer + 1) % 3;
gameState.roundCount++;
}
void resetGame() {
createDeck();
shuffleDeck();
for (Player* p : players) {
p->hand.clear();
p->isLandlord = false;
p->cardTracker.reset();
}
landlordIndex = -1;
landlordCards.clear();
currentPlayer = 0;
passCount = 0;
lastGroup = CardGroup();
gameEnded = false;
winner = -1;
gameState = GameState();
}
void displayGameState() {
cout << "\n===== 当前游戏状态 =====";
for (Player* p : players) {
cout << "\n" << p->name;
if (p->isLandlord) cout << " (地主)";
cout << ": " << p->hand.size() << "张牌";
}
cout << "\n地主剩余牌: " << gameState.landlordRemainingCards << "张";
cout << "\n回合: " << gameState.roundCount;
cout << "\n======================\n";
}
string cardTypeToString(CardType type) {
switch(type) {
case CardType::SINGLE: return "单张";
case CardType::PAIR: return "对子";
case CardType::TRIPLET: return "三张";
case CardType::TRIPLET_WITH_SINGLE: return "三带一";
case CardType::TRIPLET_WITH_PAIR: return "三带二";
case CardType::STRAIGHT: return "顺子";
case CardType::STRAIGHT_PAIRS: return "连对";
case CardType::BOMB: return "炸弹";
case CardType::ROCKET: return "火箭";
case CardType::FOUR_WITH_TWO: return "四带二";
case CardType::PLANE: return "飞机";
case CardType::PLANE_WITH_SINGLES: return "飞机带单";
case CardType::PLANE_WITH_PAIRS: return "飞机带对";
default: return "未知牌型";
}
}
public:
DouDiZhuGame() {
players.push_back(new HumanPlayer(0));
players.push_back(new AIPlayer("电脑1", 1));
players.push_back(new AIPlayer("电脑2", 2));
}
~DouDiZhuGame() {
for (Player* p : players) {
delete p;
}
}
void startGame() {
cout << "===== 斗地主游戏开始 =====" << endl;
char choice;
cout << "是否启用记牌器? (y/n): ";
cin >> choice;
enableTracker = (choice == 'y' || choice == 'Y');
if (enableTracker) {
cout << "记牌器已启用,将在你的回合显示剩余牌信息\n";
} else {
cout << "记牌器未启用\n";
}
resetGame();
for (Player* p : players) {
p->cardTracker.setInitialDeck(deck);
p->cardTracker.enable(enableTracker);
}
dealCards();
players[0]->printHand();
callLandlord();
if (landlordIndex != -1) {
cout << "\n===== 游戏正式开始! =====" << endl;
while (!gameEnded) {
displayGameState();
playTurn();
}
cout << "\n===== 游戏结束! =====" << endl;
cout << "获胜者: " << players[winner]->name;
if (players[winner]->isLandlord) {
cout << " (地主)";
} else {
cout << " (农民)";
}
for (Player* p : players) {
if (p != players[winner] && !p->hand.empty()) {
cout << "\n" << p->name << " 剩余手牌: ";
for (const Card& c : p->hand) {
cout << c.toString() << " ";
}
}
}
cout << "\n====================\n";
}
}
};
void displayTitle() {
cout << "==================================\n";
cout << " 智能斗地主游戏 C++版 \n";
cout << "==================================\n";
cout << "游戏特点:\n";
cout << "- 改进叫地主机制(可多人抢地主)\n";
cout << "- 优化AI叫地主策略\n";
cout << "- 增强牌型识别(顺子、连对、飞机)\n";
cout << "- 完善地主/农民策略系统\n";
cout << "- 智能AI避免浪费大牌\n";
cout << "- 残局针对性策略\n";
cout << "- 记牌与预测系统\n";
cout << "==================================\n\n";
}
int main() {
displayTitle();
DouDiZhuGame game;
game.startGame();
return 0;
}
全部评论 3
%%%
2025-07-19 来自 上海
0建议搞个头衔,欢乐豆和存档
2025-07-19 来自 浙江
0逆天
2025-07-18 来自 福建
0
有帮助,赞一个