用C++写一个实现斗地主功能的程序
时间: 2023-09-15 14:21:31 浏览: 176
以下是一个简单实现斗地主功能的C++程序,仅供参考:
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
#include <chrono>
// 定义扑克牌结构体
struct Card {
int value; // 牌面大小,取值范围为 3-17,分别代表 3-K、A、2、小王、大王
int suit; // 花色,取值范围为 0-3,分别代表黑桃、红心、梅花、方块
};
// 定义比较器,用于排序
bool cmp(const Card& a, const Card& b) {
if (a.value != b.value) {
return a.value < b.value;
} else {
return a.suit < b.suit;
}
}
// 打印一张牌
void printCard(const Card& card) {
std::string suit;
switch (card.suit) {
case 0:
suit = "♠";
break;
case 1:
suit = "♥";
break;
case 2:
suit = "♣";
break;
case 3:
suit = "♦";
break;
}
std::string value;
switch (card.value) {
case 11:
value = "J";
break;
case 12:
value = "Q";
break;
case 13:
value = "K";
break;
case 14:
value = "A";
break;
case 15:
value = "2";
break;
case 16:
value = "Little Joker";
break;
case 17:
value = "Big Joker";
break;
default:
value = std::to_string(card.value);
break;
}
std::cout << suit << value << " ";
}
// 打印一组牌
void printCards(const std::vector<Card>& cards) {
for (const auto& card : cards) {
printCard(card);
}
std::cout << std::endl;
}
// 初始化一副牌
std::vector<Card> initCards() {
std::vector<Card> cards;
for (int i = 3; i <= 17; i++) {
for (int j = 0; j < 4; j++) {
Card card = {i, j};
cards.push_back(card);
}
}
Card littleJoker = {16, -1};
cards.push_back(littleJoker);
Card bigJoker = {17, -1};
cards.push_back(bigJoker);
return cards;
}
// 洗牌
void shuffleCards(std::vector<Card>& cards) {
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); // 以当前时间为随机种子
std::shuffle(cards.begin(), cards.end(), std::default_random_engine(seed));
}
// 发牌,返回三个玩家的手牌
std::vector<std::vector<Card>> dealCards(const std::vector<Card>& cards) {
std::vector<std::vector<Card>> hands(3);
for (int i = 0; i < 51; i++) {
hands[i % 3].push_back(cards[i]);
}
// 将最后三张牌作为底牌
std::vector<Card> bottomCards(&cards[51], &cards[54]);
hands.push_back(bottomCards);
return hands;
}
// 判断一组牌是否能出
bool canPlay(const std::vector<Card>& cards) {
int size = cards.size();
if (size == 1) { // 单牌
return true;
} else if (size == 2) { // 对子、王炸
if (cards[0].value == cards[1].value) {
return true;
} else if (cards[0].value == 16 && cards[1].value == 17) {
return true;
} else {
return false;
}
} else if (size == 3) { // 三不带
if (cards[0].value == cards[1].value && cards[0].value == cards[2].value) {
return true;
} else {
return false;
}
} else if (size == 4) { // 炸弹、三带一
if (cards[0].value == cards[1].value && cards[0].value == cards[2].value && cards[0].value == cards[3].value) { // 炸弹
return true;
} else if ((cards[0].value == cards[1].value && cards[0].value == cards[2].value) || (cards[1].value == cards[2].value && cards[1].value == cards[3].value)) { // 三带一
return true;
} else {
return false;
}
} else if (size == 5) { // 顺子、三带二
bool isStraight = true;
for (int i = 0; i < 4; i++) {
if (cards[i].value != cards[i+1].value-1) {
isStraight = false;
break;
}
}
if (isStraight) { // 顺子
return true;
} else if ((cards[0].value == cards[1].value && cards[0].value == cards[2].value && cards[3].value == cards[4].value)
|| (cards[0].value == cards[1].value && cards[2].value == cards[3].value && cards[2].value == cards[4].value)) { // 三带二
return true;
} else {
return false;
}
} else if (size == 6) { // 连对、飞机不带
bool isStraight = true;
for (int i = 0; i < 5; i += 2) {
if (cards[i].value != cards[i+1].value || cards[i].value != cards[i+2].value-1) {
isStraight = false;
break;
}
}
if (isStraight) { // 连对
return true;
} else if (cards[0].value == cards[1].value && cards[0].value == cards[2].value && cards[3].value == cards[4].value && cards[3].value == cards[5].value) { // 飞机不带
return true;
} else {
return false;
}
} else if (size >= 8 && size % 2 == 0) { // 连对、飞机带单、飞机带双
bool isStraight = true;
for (int i = 0; i < size-1; i += 2) {
if (cards[i].value != cards[i+1].value || (i < size-2 && cards[i].value != cards[i+2].value-1)) {
isStraight = false;
break;
}
}
if (isStraight) { // 连对
return true;
}
int count = size / 5;
bool isPlane = true;
for (int i = 0; i < count; i++) {
if (cards[i*5].value != cards[i*5+1].value || cards[i*5].value != cards[i*5+2].value) {
isPlane = false;
break;
}
}
if (isPlane) {
int singleCount = 0, doubleCount = 0;
for (int i = 3*count; i < size; i++) {
if (cards[i].value == cards[i+1].value) {
doubleCount++;
i++;
} else {
singleCount++;
}
}
if (singleCount == count || doubleCount == count) { // 飞机带单或双
return true;
}
}
return false;
} else {
return false;
}
}
// 判断一组牌是否能压住上一手牌
bool canBeat(const std::vector<Card>& lastCards, const std::vector<Card>& cards) {
if (lastCards.empty()) { // 上一手牌为空,当前手牌可以出
return true;
}
if (!canPlay(cards)) { // 当前手牌不合法
return false;
}
if (cards.size() != lastCards.size()) { // 牌数不同,无法比较
return false;
}
if (cards.back().value == 17) { // 大王必胜
return true;
}
if (lastCards.back().value == 16 && cards.back().value != 17) { // 上一手牌为小王,当前手牌必须为大王
return false;
}
if (cards.back().value != lastCards.back().value) { // 牌面大小不同,无法比较
return false;
}
return true;
}
// 找出一组牌中最小的一张牌
Card findMinCard(const std::vector<Card>& cards) {
Card minCard = cards[0];
for (const auto& card : cards) {
if (card.value < minCard.value) {
minCard = card;
} else if (card.value == minCard.value && card.suit < minCard.suit) {
minCard = card;
}
}
return minCard;
}
// 玩家出牌
std::vector<Card> playCards(const std::vector<Card>& handCards, const std::vector<Card>& lastCards) {
std::vector<Card> cards;
if (lastCards.empty()) { // 上一手牌为空,随便出
cards = std::vector<Card>(handCards.begin(), handCards.begin()+1);
} else { // 上一手牌不为空,找出合法的牌
for (int i = 0; i < handCards.size(); i++) {
std::vector<Card> tempCards = lastCards;
tempCards.push_back(handCards[i]);
if (canPlay(tempCards)) {
cards.push_back(handCards[i]);
}
}
if (!cards.empty()) { // 手中有能出的牌
if (canBeat(lastCards, cards)) { // 可以压住上一手牌
if (cards.size() == 1) { // 只有一张牌可出,直接出
return cards;
} else { // 多张牌可出,找出最小的一张牌出
return std::vector<Card>{findMinCard(cards)};
}
} else { // 不能压住上一手牌,不出
return std::vector<Card>();
}
} else { // 手中没有能出的牌,不出
return std::vector<Card>();
}
}
std::sort(cards.begin(), cards.end(), cmp);
return cards;
}
int main() {
std::vector<Card> cards = initCards();
shuffleCards(cards);
std::vector<std::vector<Card>> hands = dealCards(cards);
std::vector<Card> bottomCards = hands.back();
hands.pop_back();
std::cout << "Bottom cards: ";
printCards(bottomCards);
for (int i = 0; i < 3; i++) {
std::sort(hands[i].begin(), hands[i].end(), cmp);
std::cout << "Player " << i+1 << " cards: ";
printCards(hands[i]);
}
std::vector<Card> lastCards;
int currentPlayer = 0;
while (!hands[currentPlayer].empty()) {
std::cout << "Player " << currentPlayer+1 << " turn." << std::endl;
std::vector<Card> playedCards = playCards(hands[currentPlayer], lastCards);
if (playedCards.empty()) {
std::cout << "Player " << currentPlayer+1 << " pass." << std::endl;
} else {
std::cout << "Player " << currentPlayer+1 << " played: ";
printCards(playedCards);
hands[currentPlayer].erase(std::remove_if(hands[currentPlayer].begin(), hands[currentPlayer].end(), [&](const Card& card) {
return std::find(playedCards.begin(), playedCards.end(), card) != playedCards.end();
}), hands[currentPlayer].end());
lastCards = playedCards;
}
currentPlayer = (currentPlayer + 1) % 3;
}
std::cout << "Game over." << std::endl;
return 0;
}
```
程序实现了斗地主的基本功能,包括洗牌、发牌、出牌、判断是否能出、判断是否能压住上一手牌等。但是由于策略比较简单,AI的表现可能不太好,仅供参考。
阅读全文