网站做qq登录,创建网站需要什么条件,在线制作图片上加字,需要外包团队做网站怎么提需求#x1f31f; 嗨#xff0c;我是LucianaiB#xff01;
#x1f30d; 总有人间一两风#xff0c;填我十万八千梦。
#x1f680; 路漫漫其修远兮#xff0c;吾将上下而求索。
C语言之斗地主游戏
目录
程序概述程序设计 Card类CardGroup类Player类LastCards类Land… 嗨我是LucianaiB 总有人间一两风填我十万八千梦。 路漫漫其修远兮吾将上下而求索。
C语言之斗地主游戏
目录
程序概述程序设计 Card类CardGroup类Player类LastCards类Landlords类 游戏流程特点与功能 牌型判断AI提示交互性随机性 测试与运行总体评价附录代码
本文介绍了一个基于C实现的简单斗地主游戏程序。该程序模拟了斗地主的基本规则和流程包括发牌、抢地主、出牌以及胜负判定等功能。程序的核心由多个类组成包括Card表示单张牌、CardGroup表示一组牌、Player表示玩家、LastCards用于记录上家出的牌和Landlords用于管理整个游戏流程。
程序设计
程序通过Card类定义了牌的基本属性如牌面值、花色和显示方法。CardGroup类用于管理一组牌并提供牌型判断和大小比较的功能。Player类则管理玩家手中的牌并提供出牌和提示功能。LastCards类用于记录上家出的牌并提供查找可打得过的牌的功能。Landlords类作为游戏的核心负责初始化游戏、发牌、抢地主、轮流出牌以及判断游戏结束等逻辑。
游戏流程
游戏开始时程序通过洗牌和分牌将54张牌随机分配给三个玩家并通过抢地主环节确定地主玩家。地主玩家获得额外的三张底牌后游戏正式开始。玩家按顺序出牌每次出牌需要比上家的牌大或者选择不出。当某个玩家手中的牌全部出完时游戏结束程序会判断地主是否获胜。
特点与功能
牌型判断程序能够准确判断牌型如单牌、对子、三带一、炸弹等并根据牌型和牌的大小进行比较。AI提示非地主玩家在出牌时程序会自动提示可打得过的牌提高了游戏的流畅性。交互性程序通过控制台输入输出与用户交互用户可以选择是否抢地主、出牌以及是否继续游戏。随机性通过随机洗牌和抢地主环节增加了游戏的趣味性和不确定性。
测试与运行
程序在测试中表现出了良好的稳定性和正确性。玩家可以自由选择出牌策略程序会根据规则判断出牌是否合法并在游戏结束后输出胜负结果。用户可以通过简单的命令行交互体验完整的斗地主游戏流程。
总体评价
本文介绍了一个基于C实现的斗地主游戏程序模拟了斗地主的基本规则和流程包括发牌、抢地主、出牌和胜负判定等功能。程序的核心由多个类组成如Card、CardGroup、Player、LastCards和Landlords通过面向对象编程的方式实现了游戏的完整逻辑。
在程序设计中Card类用于定义单张牌的基本属性如牌面值、花色和显示方法。CardGroup类管理一组牌并提供牌型判断和大小比较的功能。Player类管理玩家手中的牌并提供出牌和提示功能。LastCards类用于记录上家出的牌并提供查找可打得过的牌的功能。Landlords类作为游戏的核心负责初始化游戏、发牌、抢地主、轮流出牌以及判断游戏结束等逻辑。
游戏流程从洗牌和分牌开始通过抢地主环节确定地主玩家。地主获得额外三张底牌后游戏正式开始。玩家按顺序出牌每次出牌需要比上家的牌大或者选择不出。当某个玩家手中的牌全部出完时游戏结束程序会判断地主是否获胜。 该程序具有以下特点
牌型判断能够准确判断牌型如单牌、对子、三带一、炸弹等并根据牌型和牌的大小进行比较。
AI提示非地主玩家在出牌时程序会自动提示可打得过的牌提高了游戏的流畅性。
交互性通过控制台输入输出与用户交互用户可以选择是否抢地主、出牌以及是否继续游戏。
随机性通过随机洗牌和抢地主环节增加了游戏的趣味性和不确定性。
在测试中程序表现出良好的稳定性和正确性用户可以通过简单的命令行交互体验完整的斗地主游戏流程。该程序不仅实现了斗地主的基本规则还通过类的设计和封装展示了面向对象编程的思想。代码结构清晰易于理解和扩展适合用于学习和研究C编程以及游戏开发。
附录代码
#include iostream
#includevector
#includeassert.h
#includestring
#includestdio.h
#includealgorithm
#includetime.husing namespace std;#define PLAYERCOUNT 3
#define CARDSCOUNT 54
#define CURRENTPLAYER 0
#define VALUECOUNT 17
#define ERROR -1
using namespace std;
int scnt0;
const char toFigure[]34567890JQKA 2YZ;enum COLOR{ //花色显示ASCII: 3~6
eHEART3,//红桃
eDIAMOND4,//方片
eCLUB5, //草花
eSPADE6 //黑桃
};class Card;
class CardsType;
class CardGroup;
class Player;
class Landlords;
class LastCards;
bool makeChoice(string tip);
bool cmp(Card* a,Card* b);
class Card{
public:
char figure;
COLOR color;
int value;
Card(char _figure,COLOR _color){figure_figure;color_color;valuecalValue();
}
int calValue(){for(int i0;toFigure[i];i){if(toFigure[i]figure){return i;}}return ERROR;
}void print() {assert(value ! ERROR);switch (color) {case eHEART:cout ♥; // 红桃break;case eDIAMOND:cout ♦; // 方片break;case eCLUB:cout ♣; // 草花break;case eSPADE:cout ♠; // 黑桃break;default:cout ?; // 未知花色break;}cout figure ;}
};
class CardsType{
public:
//为了规范查找对应牌的方法
//统一为3个参数cnt1、isContinuous、cnt2
int typeId;
string typeStr;
int cnt1,cnt2;
bool isContinuous;
CardsType(){typeIdERROR;
}
bool operator (const CardsType other)const{return this-typeIdother.typeId;
}
void init(char* _typeStr,int _typeId,int _cnt1,bool _isContinuous,int _cnt2){cnt1_cnt1;isContinuous_isContinuous;cnt2_cnt2;typeStr_typeStr;typeId_typeId;
}
};
class CardGroup{
public:
vectorCard* cards;
CardsType type;
void calType(){int i,ncards.size();//init(typeStr,typeId,cnt1,isContinuous,cnt2)if(n0){type.init(不出,14,0,0,0);return;}if(n2cards[0]-value15cards[1]-value14){type.init(王炸,0,0,0,0);return;}//统计同点数牌有多少张int cntFlag[VALUECOUNT]{0};for(i0;in;i){cntFlag[cards[i]-value];}//统计点数最多和最少的牌int maxCnt0,minCnt4;for(i0;iVALUECOUNT;i){if(maxCntcntFlag[i]){maxCntcntFlag[i];}if(cntFlag[i]minCntcntFlag[i]){minCntcntFlag[i];}}if(n4maxCnt4){type.init(炸弹,1,4,0,0);return;}if(n1){type.init(单牌,2,1,0,0);return;}if(n2maxCnt2){type.init(对子,3,2,0,0);return;}if(n3maxCnt3){type.init(三张 ,4,3,0,0);return;}if(n4maxCnt3){type.init(三带一,5,3,0,1);return;}if(n5maxCnt3minCnt2){type.init(三带一对,6,3,0,2);return;}if(n6maxCnt4){type.init(四带二,7,4,0,1);return;}if(n8maxCnt4minCnt2){type.init(四带二,8,4,0,2);return;}if(n5maxCnt1cards[0]-valuecards[n-1]-valuen-1){type.init(顺子,9,1,1,0);return;}if(n6maxCnt2minCnt2cards[0]-valuecards[n-1]-valuen/2-1){type.init(连对,10,2,1,0);return;}int fjCnt;//统计连续且大于3三张的牌for(i0;iVALUECOUNT cntFlag[i]3;i);for(fjCnt0;iVALUECOUNT cntFlag[i]3;i,fjCnt);if(fjCnt1){if(nfjCnt*3)type.init(飞机,11,3,1,0);else if(nfjCnt*4)type.init(飞机,12,3,1,1);else if(nfjCnt*5minCnt2)type.init(飞机,13,3,1,2);}
}
void init(string inputStr, vectorCard* cardsHolded){this-cards.clear();//不出if(inputStrN){this-calType();return;}int i,j;//输入合法性判断for(i0;iinputStr.size();i){bool findfalse;for(j0;toFigure[j];j){if(inputStr[i]toFigure[j]){findtrue;break;}}if(findfalse){//输入字符不在toFigure中return;}}//查找手中有没有这些牌int visitFlag[20]{0};for(i0;iinputStr.size();i){Card *findNULL;for(j0;jcardsHolded.size();j){if(!visitFlag[j]cardsHolded[j]-figureinputStr[i]){visitFlag[j]1;findcardsHolded[j];break;}}if(find){this-cards.push_back(find);}else{coutinputStr[i];cout没有找到\t;this-cards.clear();return;}}//end for(i0;iinputStr.size();i)this-arrange();
}
void init(vectorCard* newCards){this-cardsnewCards;this-arrange();
}
bool isCanBeat(CardGroup cardGroup){if(cardGroup.type.typeStr王炸){return false;}else if(this-type.typeStr王炸){return true;}else if(cardGroup.typethis-type this-type.typeStr炸弹){return value()cardGroup.value();}else if(cardGroup.type.typeStr炸弹){return false;}else if(this-type.typeStr炸弹){return true;}else if(cardGroup.typethis-type this-cards.size()cardGroup.cards.size()){return this-value()cardGroup.value();}else{return false;}
}
int value(){//计算牌组权值int i;if(type.typeStr三带一||type.typeStr三带一对||type.typeStr飞机){for(i2;icards.size();i){if(cards[i]-valuecards[i-2]-value){return cards[i]-value;}}}if(type.typeStr四带二){for(i3;icards.size();i){if(cards[i]-valuecards[i-3]-value){return cards[i]-value;}}}return cards[0]-value;
}
void arrange(){//整理排序、计算类型// sort(this-cards.begin(),this-cards.end(),cmp);this-calType();
}
};
class LastCards{
static LastCards *lastCards;
public:
Player *player;
CardGroup cardGroup;
static LastCards* inst(){//单例模式if(lastCardsNULL){lastCardsnew LastCards();}return lastCards;
}
vectorCard* findCanBeatFrom(vectorCard* cardsHolded){//查找能打得过的牌int i,j,k,ncardsHolded.size(),mcardGroup.cards.size();string typeStrcardGroup.type.typeStr;vectorCard* ret;if(typeStr王炸||nm){//打不过返回空数组return ret;}int valuecardGroup.value();//统计各点牌出现的次数int cntFlag[VALUECOUNT]{0};for(i0;in;i){cntFlag[cardsHolded[i]-value];}int continuousCount1;if(cardGroup.type.isContinuous){continuousCountm/(cardGroup.type.cnt1cardGroup.type.cnt2);}bool findFirstFigure;//coutcontinuousCountcontinuousCountendl;for(ivalue1;iVALUECOUNT;i){findFirstFiguretrue;for(j0;jcontinuousCount;j){if(cntFlag[i-j]cardGroup.type.cnt1){findFirstFigurefalse;break;}}if(findFirstFigure){ret.clear();int firstFigurei;//cout查找cardGroup.type.cnt1个firstFigure3endl;for(k0,j0;kcardsHolded.size() jcontinuousCount;k){if(cardsHolded[k]-valuefirstFigure-j){for(int kk0;j0kkcardGroup.type.cnt1;kk){ret.push_back(cardsHolded[kkk]);}j;}}if(cardGroup.type.cnt20){int SecondFigures[5];int SecondCountcontinuousCount;if(cardGroup.type.typeStr四带二)SecondCount2;bool findSecondFiguretrue;for(j0,k-1;jSecondCount findSecondFigure;j){findSecondFigurefalse;for(k;kVALUECOUNT;k){SecondFigures[j]k;if(cntFlag[k]cardGroup.type.cnt2 cntFlag[k]cardGroup.type.cnt1){findSecondFiguretrue;break;}}}if(findSecondFigure){//cout查找SecondFigure cardGroup.type.cnt2个SecondFigures[0]3endl;//coutSecondCount SecondCountendl;//for(i0;iSecondCount;i)coutSecondFigures[i]SecondFigures[i]endl;for(i0;iSecondCount;i){for(j0;jcardsHolded.size();){if(cardsHolded[j]-valueSecondFigures[i]){for(k0;kcardGroup.type.cnt2;k){//cout添加cardsHolded[j]-value3endl;ret.push_back(cardsHolded[jk]);}do{j;}while(jcardsHolded.size()cardsHolded[j]-valueSecondFigures[i]);}else{j;}}}return ret;}//if(findSecondFigure)}//end if(cardGroup.type.cnt20)else{return ret;}}//end if(findFirstFigure)}//end for(ivalue1;iVALUECOUNT;i)ret.clear();//没牌打得过时查找有没有炸弹if(typeStr!炸弹){for(icardsHolded.size()-1;i3;i--){if(cardsHolded[i]-valuecardsHolded[i-3]-value){for(j0;j4;j){ret.push_back(cardsHolded[i-j]);}break;}}}return ret;
}//end vectorCard* findCanBeatFrom()
};
LastCards* LastCards::lastCards NULL;
class Player{
public:
string name;
vectorCard* cards;
void arrange(){sort(cards.begin(),cards.end(),cmp);
}
void print(){coutthis-name:\t;for(int i0;icards.size();i){cards[i]-print();}cout[cards.size()]\n;
}
vectorCard* tip(){//提示功能,使自己最小一张连最长CardGroup ret;string temp;int j,k,mcards.size();for(j0;jm;j){temp;for(kj;km;k){tempcards[k]-figure;}ret.init(temp,cards);if(ret.type.typeId!ERROR){return ret.cards;}}ret.cards.clear();return ret.cards;
}
void chupai(CardGroup cardGroup){//出牌coutthis-name:\t;coutcardGroup.type.typeStr ;for(int i0;icardGroup.cards.size();i){cardGroup.cards[i]-print();this-cards.erase(find(this-cards.begin(),this-cards.end(),cardGroup.cards[i]));}cout\t[this-cards.size()]\n;if(cardGroup.type.typeStr!不出){//记录到 LastCards 中LastCards::inst()-playerthis;LastCards::inst()-cardGroup.init(cardGroup.cards);}
}
};
class Landlords{
Player *player[PLAYERCOUNT];
bool finished,youWin,landlordWin;
int landlordIndex;
Card *cards[CARDSCOUNT];
public:
Landlords(){int i0,j0,k0;for(i0;iPLAYERCOUNT;i){this-player[i]new Player();}//54张牌初始化for(ki0;i14;i){if(toFigure[i] ){continue;}for(COLOR coloreHEART;coloreSPADE;color(COLOR)(color1)){this-cards[k]new Card(toFigure[i],color);}}this-cards[k]new Card(Y,eSPADE);this-cards[k]new Card(Z,eHEART);
}
~Landlords(){for(int i0;iPLAYERCOUNT;i){delete this-player[i];}for(int i10;i1CARDSCOUNT;i1){delete this-cards[i1];}
}
void init(){player[CURRENTPLAYER]-nameBice;player[1]-name玩家2;player[2]-name玩家3;finishedfalse;youWinfalse;landlordWinfalse;//抢地主landlordIndexERROR;while(landlordIndexERROR){srand((int)time(0));shuffle();landlordIndexchooseLandlord();}coutplayer[landlordIndex]-name\t成为地主\n\n;this-add3Cards();LastCards::inst()-playerplayer[landlordIndex];
}
void startGame(){string inputSrt;CardGroup inputCards;for(int iTurnslandlordIndex;!finished;iTurns){if(iTurnsPLAYERCOUNT){iTurns0;}if(iTurnsCURRENTPLAYER){coutendl;player[iTurns]-print();cout输入提示Z大王 Y小王 010 N不要 输入可无序 例如:JKQ0A9\n请出牌\t;do{cininputSrt;inputCards.init(inputSrt,player[iTurns]-cards);}while(check(inputCards)false);}else{if(player[iTurns]LastCards::inst()-player){//若是上次出牌的是自己启用提示功能inputCards.init(player[iTurns]-tip());}else{//查找能打得过上家的牌inputCards.init(LastCards::inst()-findCanBeatFrom(player[iTurns]-cards));}}player[iTurns]-chupai(inputCards);//出牌if(player[iTurns]-cards.size()0){//玩家手中没牌了游戏结束finishedtrue;landlordWiniTurnslandlordIndex;if(landlordWin){youWinlandlordIndexCURRENTPLAYER;}else{youWinlandlordIndex!CURRENTPLAYER;}}}cout\n_________________________ (youWin?You Win!:You Lose!) _________________________\n\n;
}
void add3Cards(){cout地主3张牌:\t;for(int iPLAYERCOUNT*17;iCARDSCOUNT;i){this-cards[i]-print();player[landlordIndex]-cards.push_back(cards[i]);}coutendl;player[landlordIndex]-arrange();
}
int chooseLandlord(){cout\n_________________________ 抢地主 _________________________\n\n;int first-1,last,cnt0,i,jrand()%PLAYERCOUNT;bool decision;for(i0;iPLAYERCOUNT;i,j2?j0:j){if(jCURRENTPLAYER){decisionmakeChoice(是否抢地主(Y抢/N不抢):);}else{decisionrand()%2;}if(decision){cnt;lastj;if(first-1){firstj;}coutthis-player[j]-name\t抢地主\n;}else{coutthis-player[j]-name\t没有抢\n;}}if(cnt0){cout没人抢重新发牌\n;return ERROR;}if(cnt1){//第一轮只有一人抢地主return first;}else{//最后一次争抢if(firstCURRENTPLAYER){decisionmakeChoice(是否抢地主(Y抢/N不抢):);}else{decisionrand()%2;}if(decision){coutthis-player[first]-name\t抢地主\n;return first;}else{coutthis-player[first]-name\t没有抢\n;return last;}}
}
void shuffle(){int i,j,k;//洗牌for(i0;iCARDSCOUNT;i){swap(this-cards[i],this-cards[rand()%CARDSCOUNT]);}//分牌for(ki0;iPLAYERCOUNT;i){this-player[i]-cards.clear();for(j0;j17;j){this-player[i]-cards.push_back(this-cards[k]);}this-player[i]-arrange();//整理this-player[i]-print();}
}
bool check(CardGroup *cardGroup){if(cardGroup-type.typeIdERROR){cout出牌错误重新输入\n;return false;}else if(cardGroup-type.typeStr不出){return true;}else if(LastCards::inst()-player!player[CURRENTPLAYER]!cardGroup-isCanBeat(LastCards::inst()-cardGroup)){cout打不过重新输入\n;return false;}else{return true;}
}
};
int main(){
Landlords *landlordsnew Landlords();
do{landlords-init();//发牌、抢地主landlords-startGame();//游戏开始
}while(makeChoice(\n是否继续游戏Y继续/N结束: ));
delete landlords;
return 0;
}
bool makeChoice(string tip){
couttip;
string input;
cininput;
return inputY||inputy;
}
bool cmp(Card* a,Card* b){
if(a-valueb-value){return a-colorb-color;
}else{return a-valueb-value;
}
} 嗨我是[LucianaiB](https://lucianaib.blog.csdn.net/ “LucianaiB”)。如果你觉得我的分享有价值不妨通过以下方式表达你的支持 点赞来表达你的喜爱 关注以获取我的最新消息 评论与我交流你的见解。我会继续努力为你带来更多精彩和实用的内容。 点击这里[LucianaiB](https://lucianaib.blog.csdn.net/ “LucianaiB”) 获取最新动态⚡️ 让信息传递更加迅速。