斗地主c++
2025-07-30 10:08:24
发布于:广东
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <windows.h>
using namespace std;
// 卡牌结构体
struct Card {
string suit; // 花色
string rank; // 点数
int value; // 用于比较的数值
};
// 玩家类
struct Player {
vector<Card> hand; // 手牌
string name; // 玩家名称
bool isLandlord; // 是否是地主
};
// 清屏函数
void clearScreen() {
system("cls");
}
// 延时函数
void delay(int milliseconds) {
Sleep(milliseconds);
}
// 创建一副扑克牌(包含大小王)
vector<Card> createDeck() {
vector<Card> deck;
vector<string> suits = {"红桃", "方块", "黑桃", "梅花"};
vector<string> ranks = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
// 添加普通牌
for (const string& suit : suits) {
for (int i = 0; i < ranks.size(); i++) {
Card card;
card.suit = suit;
card.rank = ranks[i];
card.value = i + 1; // 3最小(1),2最大(13)
deck.push_back(card);
}
}
// 添加大小王
Card joker1, joker2;
joker1.suit = "王牌";
joker1.rank = "小王";
joker1.value = 14;
joker2.suit = "王牌";
joker2.rank = "大王";
joker2.value = 15;
deck.push_back(joker1);
deck.push_back(joker2);
return deck;
}
// 洗牌
void shuffleDeck(vector<Card>& deck) {
srand(time(0));
for (int i = 0; i < deck.size(); i++) {
int j = rand() % deck.size();
swap(deck[i], deck[j]);
}
}
// 给手牌排序
void sortHand(vector<Card>& hand) {
sort(hand.begin(), hand.end(), [](const Card& a, const Card& b) {
return a.value < b.value;
});
}
// 显示单张牌
void displayCard(const Card& card) {
cout << card.suit << card.rank << " ";
}
// 显示手牌
void displayHand(const vector<Card>& hand) {
for (size_t i = 0; i < hand.size(); i++) {
cout << "[" << i+1 << "]"; // 显示序号
displayCard(hand[i]);
if ((i+1) % 8 == 0) cout << endl; // 每8张牌换行
}
cout << endl;
}
// 叫地主环节
int callLandlord(Player players[]) {
clearScreen();
cout << "=== 叫地主环节 ===" << endl << endl;
int landlordIndex = -1;
int currentPlayer = rand() % 3; // 随机决定叫地主顺序的起始玩家
for (int i = 0; i < 3; i++) {
int idx = (currentPlayer + i) % 3;
clearScreen();
cout << "=== 叫地主环节 ===" << endl << endl;
cout << players[idx].name << ",是否要当地主?(1-叫地主,0-不叫):";
int choice;
cin >> choice;
if (choice == 1) {
landlordIndex = idx;
players[idx].isLandlord = true;
break;
}
}
// 如果没人叫地主,随机选择一个
if (landlordIndex == -1) {
landlordIndex = rand() % 3;
players[landlordIndex].isLandlord = true;
clearScreen();
cout << "无人叫地主,随机选择 " << players[landlordIndex].name << " 作为地主!" << endl;
delay(1500);
}
return landlordIndex;
}
// 检查牌型是否合法
bool isValidMove(const vector<Card>& lastMove, const vector<Card>& currentMove) {
// 简化版:只实现单牌、对子、三张、顺子、炸弹的判断
if (lastMove.empty()) return true; // 首家出牌任意合法牌型
// 炸弹可以打任何非炸弹牌型
bool isLastBomb = (lastMove.size() == 2 &&
((lastMove[0].rank == "小王" && lastMove[1].rank == "大王") ||
(lastMove[0].value == lastMove[1].value && lastMove[0].value >= 13)));
bool isCurrentBomb = (currentMove.size() == 2 &&
((currentMove[0].rank == "小王" && currentMove[1].rank == "大王") ||
(currentMove[0].value == currentMove[1].value && currentMove[0].value >= 13)));
if (isCurrentBomb) {
if (!isLastBomb) return true;
// 炸弹之间比大小
return currentMove[0].value > lastMove[0].value;
}
if (isLastBomb) return false; // 非炸弹不能打炸弹
// 牌型必须相同
if (lastMove.size() != currentMove.size()) return false;
// 单牌
if (lastMove.size() == 1) {
return currentMove[0].value > lastMove[0].value;
}
// 对子
if (lastMove.size() == 2 &&
lastMove[0].value == lastMove[1].value &&
currentMove[0].value == currentMove[1].value) {
return currentMove[0].value > lastMove[0].value;
}
// 三张
if (lastMove.size() == 3 &&
lastMove[0].value == lastMove[1].value &&
lastMove[1].value == lastMove[2].value &&
currentMove[0].value == currentMove[1].value &&
currentMove[1].value == currentMove[2].value) {
return currentMove[0].value > lastMove[0].value;
}
return false; // 其他牌型在简化版中不支持
}
// 玩家出牌
vector<Card> playerTurn(Player& player, const vector<Card>& lastMove) {
clearScreen();
cout << player.name << (player.isLandlord ? "(地主)" : "(农民)") << "的回合" << endl;
cout << "你的手牌 (" << player.hand.size() << "张):" << endl;
displayHand(player.hand);
cout << endl;
if (!lastMove.empty()) {
cout << "上家出的牌:";
for (const auto& card : lastMove) {
displayCard(card);
}
cout << endl << endl;
}
vector<Card> move;
string input;
while (true) {
cout << "请选择要出的牌(输入序号,用逗号分隔,0表示不出):";
cin >> input;
if (input == "0") {
// 不出牌
return move;
}
// 解析输入的牌序号
vector<int> indices;
size_t pos = 0;
string delimiter = ",";
while ((pos = input.find(delimiter)) != string::npos) {
string token = input.substr(0, pos);
indices.push_back(stoi(token) - 1); // 转换为0-based索引
input.erase(0, pos + delimiter.length());
}
indices.push_back(stoi(input) - 1);
// 检查索引是否有效
bool validIndices = true;
for (int idx : indices) {
if (idx < 0 || idx >= (int)player.hand.size()) {
validIndices = false;
break;
}
}
if (!validIndices) {
cout << "输入无效,请重新输入!" << endl;
continue;
}
// 收集选中的牌
vector<Card> selectedCards;
for (int idx : indices) {
selectedCards.push_back(player.hand[idx]);
}
// 检查牌型是否合法
if (isValidMove(lastMove, selectedCards)) {
// 从手牌中移除选中的牌
sort(indices.rbegin(), indices.rend()); // 从大到小删除,避免索引错乱
for (int idx : indices) {
player.hand.erase(player.hand.begin() + idx);
}
return selectedCards;
} else {
cout << "牌型不合法或不能打过上家,请重新选择!" << endl;
}
}
}
// 电脑简单AI出牌
vector<Card> computerTurn(Player& player, const vector<Card>& lastMove) {
clearScreen();
cout << player.name << (player.isLandlord ? "(地主)" : "(农民)") << "正在思考..." << endl;
delay(1500);
// 简化版AI:如果是空牌堆,随机出一张单牌
if (lastMove.empty()) {
if (!player.hand.empty()) {
vector<Card> move;
move.push_back(player.hand[0]);
player.hand.erase(player.hand.begin());
return move;
}
return {};
}
// 如果有牌能打过上家,就出最小的那张能打过的牌
if (lastMove.size() == 1) {
for (size_t i = 0; i < player.hand.size(); i++) {
if (player.hand[i].value > lastMove[0].value) {
vector<Card> move;
move.push_back(player.hand[i]);
player.hand.erase(player.hand.begin() + i);
clearScreen();
cout << player.name << "出了:";
displayCard(move[0]);
cout << endl;
delay(1500);
return move;
}
}
}
// 无法出牌
clearScreen();
cout << player.name << "不出牌!" << endl;
delay(1000);
return {};
}
// 游戏主函数
void playGame() {
// 创建玩家
Player players[3];
players[0].name = "你";
players[1].name = "电脑1";
players[2].name = "电脑2";
players[0].isLandlord = false;
players[1].isLandlord = false;
players[2].isLandlord = false;
// 创建并洗牌
vector<Card> deck = createDeck();
shuffleDeck(deck);
// 留3张底牌
vector<Card> bottomCards;
for (int i = 0; i < 3; i++) {
bottomCards.push_back(deck.back());
deck.pop_back();
}
// 叫地主
int landlordIndex = callLandlord(players);
// 发牌
for (int i = 0; i < deck.size(); i++) {
players[i % 3].hand.push_back(deck[i]);
}
// 地主获得底牌
players[landlordIndex].hand.insert(players[landlordIndex].hand.end(),
bottomCards.begin(), bottomCards.end());
// 给所有玩家的手牌排序
for (int i = 0; i < 3; i++) {
sortHand(players[i].hand);
}
// 显示底牌
clearScreen();
cout << "底牌是:";
for (const auto& card : bottomCards) {
displayCard(card);
}
cout << endl << players[landlordIndex].name << "成为地主!" << endl;
delay(2000);
// 游戏主循环
int currentPlayer = landlordIndex; // 地主先出牌
vector<Card> lastMove;
int passCount = 0; // 连续不出牌次数
while (true) {
// 检查是否有人获胜
for (int i = 0; i < 3; i++) {
if (players[i].hand.empty()) {
clearScreen();
if (players[i].isLandlord) {
cout << "地主" << players[i].name << "获胜!" << endl;
} else {
cout << "农民获胜!" << endl;
}
delay(3000);
return;
}
}
// 如果连续3人不出牌,重置
if (passCount >= 2) {
lastMove.clear();
passCount = 0;
clearScreen();
cout << "所有人都不出牌,重新开始一轮!" << endl;
delay(1500);
}
// 当前玩家出牌
vector<Card> currentMove;
if (currentPlayer == 0) { // 玩家自己
currentMove = playerTurn(players[currentPlayer], lastMove);
} else { // 电脑
currentMove = computerTurn(players[currentPlayer], lastMove);
}
// 更新上一轮出牌和不出牌计数
if (currentMove.empty()) {
passCount++;
} else {
lastMove = currentMove;
passCount = 0;
}
// 切换到下一个玩家
currentPlayer = (currentPlayer + 1) % 3;
}
}
int main() {
char playAgain;
do {
playAgain = 'n';
clearScreen();
cout << "=== 欢迎来到斗地主游戏 ===" << endl << endl;
cout << "游戏规则:" << endl;
cout << "1. 先通过叫地主决定谁当地主" << endl;
cout << "2. 地主获得3张底牌,先出牌" << endl;
cout << "3. 可以出单牌、对子、三张和炸弹" << endl;
cout << "4. 先出完牌的一方获胜" << endl << endl;
cout << "按任意键开始游戏...";
system("pause > nul"); // 暂停等待用户按键
playGame();
cout << "想再玩一次吗? (y/n): ";
cin >> playAgain;
} while (playAgain == 'y' || playAgain == 'Y');
clearScreen();
cout << "感谢游玩!再见!" << endl;
delay(2000);
return 0;
}
这里空空如也
有帮助,赞一个