这是第三次写博客了,我给大家发一个c++小游戏——打飞机。

#include<bits/stdc++.h>
#define PLAYERCOUNT 3
#define CARDSCOUNT 54
#define CURRENTPLAYER 0
#define VALUECOUNT 17
#define ERROR -1using namespace std;
const char toFigure[]="34567890JQKA 2YZ";
enum COLOR{  //花色显示ASCII: 3~6eHEART=3,//红桃 eDIAMOND,//方片 eCLUB,   //草花 eSPADE   //黑桃
};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;value=calValue();}int calValue(){for(int i=0;toFigure[i];i++){if(toFigure[i]==figure){return i;}}return ERROR;}void print(){assert(value!=ERROR);if(figure=='Z'){cout<<"ZZ";}else if(figure=='Y'){cout<<"YY";}else{cout<<figure<<(char)color;}cout<<' ';}
};class CardsType{public://为了规范查找对应牌的方法//统一为3个参数cnt1、isContinuous、cnt2int typeId;string typeStr;int cnt1,cnt2;bool isContinuous;CardsType(){typeId=ERROR;}bool operator ==(const CardsType& other)const{return this->typeId==other.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:vector<Card*> cards;CardsType type;void calType(){int i,n=cards.size();//init(typeStr,typeId,cnt1,isContinuous,cnt2)if(n==0){type.init("不出",14,0,0,0);return;}if(n==2&&cards[0]->value==15&&cards[1]->value==14){type.init("王炸",0,0,0,0);return;}//统计同点数牌有多少张 int cntFlag[VALUECOUNT]={0};for(i=0;i<n;i++){cntFlag[cards[i]->value]++;}//统计点数最多和最少的牌 int maxCnt=0,minCnt=4;for(i=0;i<VALUECOUNT;i++){ if(maxCnt<cntFlag[i]){maxCnt=cntFlag[i];}if(cntFlag[i]&&minCnt>cntFlag[i]){minCnt=cntFlag[i];}}if(n==4&&maxCnt==4){type.init("炸dan",1,4,0,0);return;}if(n==1){type.init("单牌",2,1,0,0);return;}if(n==2&&maxCnt==2){type.init("对子",3,2,0,0);return;}if(n==3&&maxCnt==3){type.init("三张 ",4,3,0,0);return;}if(n==4&&maxCnt==3){type.init("三带一",5,3,0,1);return;}if(n==5&&maxCnt==3&&minCnt==2){type.init("三带一对",6,3,0,2);return;}if(n==6&&maxCnt==4){type.init("四带二",7,4,0,1);return;}if(n==8&&maxCnt==4&&minCnt==2){type.init("四带二",8,4,0,2);return;} if(n>=5&&maxCnt==1&&cards[0]->value==cards[n-1]->value+n-1){type.init("顺子",9,1,1,0);return;}if(n>=6&&maxCnt==2&&minCnt==2&&cards[0]->value==cards[n-1]->value+n/2-1){type.init("连对",10,2,1,0); return;}int fjCnt;//统计连续且大于3三张的牌 for(i=0;i<VALUECOUNT &&cntFlag[i]<3;i++);for(fjCnt=0;i<VALUECOUNT &&cntFlag[i]>=3;i++,fjCnt++);if(fjCnt>1){if(n==fjCnt*3)type.init("飞机",11,3,1,0);else if(n==fjCnt*4)type.init("飞机",12,3,1,1); else if(n==fjCnt*5&&minCnt==2)type.init("飞机",13,3,1,2); }}void init(string inputStr, vector<Card*> &cardsHolded){this->cards.clear();//不出 if(inputStr=="N"){this->calType();return;}int i,j;//输入合法性判断 for(i=0;i<inputStr.size();i++){bool find=false;for(j=0;toFigure[j];j++){ if(inputStr[i]==toFigure[j]){find=true;break;}} if(find==false){//输入字符不在toFigure中return;}}//查找手中有没有这些牌 int visitFlag[20]={0};for(i=0;i<inputStr.size();i++){Card *find=NULL;for(j=0;j<cardsHolded.size();j++){if(!visitFlag[j]&&cardsHolded[j]->figure==inputStr[i]){visitFlag[j]=1;find=cardsHolded[j];break;}}if(find){this->cards.push_back(find);}else{cout<<inputStr[i];cout<<"没有找到\t";this->cards.clear();return;}}//end for(i=0;i<inputStr.size();i++) this->arrange();}void init(vector<Card*> newCards){this->cards=newCards;this->arrange();}bool isCanBeat(CardGroup &cardGroup){if(cardGroup.type.typeStr=="王炸"){return false;}else if(this->type.typeStr=="王炸"){return true;}else if(cardGroup.type==this->type &&this->type.typeStr=="炸dan"){return value()>cardGroup.value();}else if(cardGroup.type.typeStr=="炸dan"){return false;}else if(this->type.typeStr=="炸dan"){return true;}else if(cardGroup.type==this->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(i=2;i<cards.size();i++){if(cards[i]->value==cards[i-2]->value){return cards[i]->value;}}}if(type.typeStr=="四带二"){for(i=3;i<cards.size();i++){if(cards[i]->value==cards[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(lastCards==NULL){lastCards=new LastCards();}return lastCards;}vector<Card*> findCanBeatFrom(vector<Card*> &cardsHolded){//查找能打得过的牌 int i,j,k,n=cardsHolded.size(),m=cardGroup.cards.size();string typeStr=cardGroup.type.typeStr;vector<Card*> ret;if(typeStr=="王炸"||n<m){//打不过,返回空数组 return ret;}int value=cardGroup.value();//统计各点牌出现的次数 int cntFlag[VALUECOUNT]={0};for(i=0;i<n;i++){ cntFlag[cardsHolded[i]->value]++;} int continuousCount=1;if(cardGroup.type.isContinuous){continuousCount=m/(cardGroup.type.cnt1+cardGroup.type.cnt2);}bool findFirstFigure;//cout<<"continuousCount="<<continuousCount<<endl;for(i=value+1;i<VALUECOUNT;i++){findFirstFigure=true;for(j=0;j<continuousCount;j++){ if(cntFlag[i-j]<cardGroup.type.cnt1){findFirstFigure=false;break;}}if(findFirstFigure){ret.clear();int firstFigure=i;//cout<<"查找"<<cardGroup.type.cnt1<<"个"<<firstFigure+3<<endl;for(k=0,j=0;k<cardsHolded.size() &&j<continuousCount;k++){ if(cardsHolded[k]->value==firstFigure-j){for(int kk=0;j>=0&&kk<cardGroup.type.cnt1;kk++){ ret.push_back(cardsHolded[k+kk]);} j++; }} if(cardGroup.type.cnt2>0){int SecondFigures[5];int SecondCount=continuousCount;if(cardGroup.type.typeStr=="四带二")SecondCount=2;bool findSecondFigure=true;for(j=0,k=-1;j<SecondCount &&findSecondFigure;j++){findSecondFigure=false;for(k++;k<VALUECOUNT;k++){SecondFigures[j]=k;if(cntFlag[k]>=cardGroup.type.cnt2 &&cntFlag[k]<cardGroup.type.cnt1){findSecondFigure=true;break;}}}if(findSecondFigure){//cout<<"查找SecondFigure "<<cardGroup.type.cnt2<<"个"<<SecondFigures[0]+3<<endl;//cout<<"SecondCount= "<<SecondCount<<endl;//for(i=0;i<SecondCount;i++)cout<<"SecondFigures["<<i<<"]="<<SecondFigures[i]<<endl;for(i=0;i<SecondCount;i++){ for(j=0;j<cardsHolded.size();){ if(cardsHolded[j]->value==SecondFigures[i]){for(k=0;k<cardGroup.type.cnt2;k++){//cout<<"添加"<<cardsHolded[j]->value+3<<endl;ret.push_back(cardsHolded[j+k]);}do{j++;}while(j<cardsHolded.size()&&cardsHolded[j]->value==SecondFigures[i]);}else{j++;} }} return ret;}//if(findSecondFigure) }//end if(cardGroup.type.cnt2>0)else{return ret;}}//end if(findFirstFigure)}//end for(i=value+1;i<VALUECOUNT;i++)ret.clear();//没牌打得过时查找有没有炸dan if(typeStr!="炸dan"){for(i=cardsHolded.size()-1;i>=3;i--){if(cardsHolded[i]->value==cardsHolded[i-3]->value){for(j=0;j<4;j++){ret.push_back(cardsHolded[i-j]);}break;}}}return ret;   }//end vector<Card*> findCanBeatFrom()
};
LastCards* LastCards::lastCards = NULL;class Player{public:string name;vector<Card*> cards;void arrange(){sort(cards.begin(),cards.end(),cmp);}void print(){cout<<this->name<<":\t";for(int i=0;i<cards.size();i++){cards[i]->print();}cout<<"["<<cards.size()<<"]\n";}vector<Card*> tip(){//提示功能,使自己最小一张连最长CardGroup ret;string temp;int j,k,m=cards.size();for(j=0;j<m;j++){temp="";for(k=j;k<m;k++){temp+=cards[k]->figure;}ret.init(temp,cards);if(ret.type.typeId!=ERROR){return ret.cards;}}ret.cards.clear();return ret.cards;}void chupai(CardGroup &cardGroup){//出牌 cout<<this->name<<":\t";cout<<cardGroup.type.typeStr<<' ';for(int i=0;i<cardGroup.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()->player=this;LastCards::inst()->cardGroup.init(cardGroup.cards);}}
};class Landlords{Player *player[PLAYERCOUNT];bool finished,youWin,landlordWin;int landlordIndex;Card *cards[CARDSCOUNT];public:Landlords(){int i,j,k;for(i=0;i<PLAYERCOUNT;i++){this->player[i]=new Player();}//54张牌初始化 for(k=i=0;i<14;i++){if(toFigure[i]==' '){continue;}for(COLOR color=eHEART;color<=eSPADE;color=(COLOR)(color+1)){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 i=0;i<PLAYERCOUNT;i++){delete this->player[i];}for(int i=0;i<CARDSCOUNT;i++){delete this->cards[i];}} void init(){player[CURRENTPLAYER]->name="Bice";player[1]->name="玩家2";player[2]->name="玩家3";finished=false;youWin=false;landlordWin=false;//抢地主landlordIndex=ERROR; while(landlordIndex==ERROR){srand((int)time(0));shuffle();landlordIndex=chooseLandlord();}cout<<player[landlordIndex]->name<<"\t成为地主\n\n";this->add3Cards();LastCards::inst()->player=player[landlordIndex];}void startGame(){string inputSrt;CardGroup inputCards;for(int iTurns=landlordIndex;!finished;iTurns++){if(iTurns>=PLAYERCOUNT){iTurns=0;}if(iTurns==CURRENTPLAYER){cout<<endl;player[iTurns]->print();cout<<"输入提示:Z=大王 Y=小王 0=10 输入可无序 例如:JKQ0A9\n请出牌:\t";do{cin>>inputSrt;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){//玩家手中没牌了,游戏结束 finished=true;landlordWin=iTurns==landlordIndex;if(landlordWin){youWin=landlordIndex==CURRENTPLAYER;}else{youWin=landlordIndex!=CURRENTPLAYER;}}}cout<<"\n_________________________ "<<(youWin?"You Win!":"You Lose!")<<" _________________________\n\n";}void add3Cards(){cout<<"地主3张牌:\t";for(int i=PLAYERCOUNT*17;i<CARDSCOUNT;i++){this->cards[i]->print();player[landlordIndex]->cards.push_back(cards[i]);}cout<<endl;player[landlordIndex]->arrange();}int chooseLandlord(){cout<<"\n_________________________ 抢地主 _________________________\n\n";int first=-1,last,cnt=0,i,j=rand()%PLAYERCOUNT;bool decision;for(i=0;i<PLAYERCOUNT;i++,j==2?j=0:j++){if(j==CURRENTPLAYER){decision=makeChoice("是否抢地主?(Y=抢/N=不抢):");}else{ decision=rand()%2;}if(decision){cnt++;last=j;if(first==-1){first=j;}cout<<this->player[j]->name<<"\t抢地主\n";}else{cout<<this->player[j]->name<<"\t没有抢\n";}}if(cnt==0){cout<<"没人抢,重新发牌\n";return ERROR;}if(cnt==1){//第一轮只有一人抢地主 return first;}else{//最后一次争抢 if(first==CURRENTPLAYER){decision=makeChoice("是否抢地主?(Y=抢/N=不抢):");}else{decision=rand()%2;}if(decision){cout<<this->player[first]->name<<"\t抢地主\n";return first;}else{cout<<this->player[first]->name<<"\t没有抢\n";return last;}}}void shuffle(){int i,j,k;    //洗牌 for(i=0;i<CARDSCOUNT;i++){swap(this->cards[i],this->cards[rand()%CARDSCOUNT]);}//分牌 for(k=i=0;i<PLAYERCOUNT;i++){this->player[i]->cards.clear();for(j=0;j<17;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.typeId==ERROR){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 *landlords=new Landlords();do{landlords->init();//发牌、抢地主 landlords->startGame();//游戏开始 }while(makeChoice("\n是否继续游戏?(Y=继续/N=结束): "));delete landlords;return 0;
}bool makeChoice(string tip){cout<<tip;string input;cin>>input;return input=="Y"||input=="y";
}bool cmp(Card* a,Card* b){//比较两张牌大小 if(a->value==b->value){return a->color>b->color;}else{return a->value>b->value;}
}

这个游戏不大精细,请各位多多指教!别忘了把赞留下!有兴趣可以关注我或者加我微信(13950392436)。(火箭工作室)

火箭工作室c++小游戏——打飞机相关推荐

  1. 火箭工作室c++小游戏——海战棋

    火箭工作室第一个c++开发游戏--海战棋 今天是我第一次写博客,发个小游戏给大家当做见面礼. #include <cstdio> #include <ctime> //rand ...

  2. 火箭工作室c++小游戏——坦克大战(初始版)

    今天第四次写博客,给大家发一个坦克大战的初始版,可以开外挂,要自己去探索 #include<windows.h> #include<conio.h> #include<i ...

  3. 火箭工作室c++小游戏——虫虫大乱斗

    这个游戏比较简陋,是有关奥数的.但是你一旦找到了规律以后呢就很容易了. 废话不多说,这是代码:#include<bits/stdc++.h> #include<windows.h&g ...

  4. 微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js)

    微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js) 微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞 ...

  5. 安卓小游戏:飞机大战

    安卓小游戏:飞机大战 前言 前面写了十二篇自定义view的博客,说实话写的还是有点无聊了,最近调整了一下,觉得还是要对开发有热情,就写了点小游戏,现在抽时间把博客也写一写,希望读者喜欢. 需求 这里就 ...

  6. 微信小游戏《飞机打方块》源码分享

    微信小游戏<飞机打方块>源码分享 游戏使用CocosCreator v2.4.2开发 源码:https://gitee.com/propertygame/cocos-creator3.x- ...

  7. python小游戏代码大全打枪-python实现微信小游戏打飞机代码

    以前版本的微信小游戏有一个打飞机的游戏,学完python之后我试着写了下程序去基本实现打飞机的功能,下面是小游戏打飞机的python代码 注:python中部分代码转自crossin编程教室 impo ...

  8. Java Swing 经典小游戏《飞机大战》———— (四)碰撞检测 游戏状态与得分 玩家升级

    前期回顾 Java Swing 经典小游戏<飞机大战>---- (一)获取素材,创建窗口,添加滚动背景,双缓冲 Java Swing 经典小游戏<飞机大战>---- (二)玩家 ...

  9. python飞机大战加背景音乐_python实现飞机大战小游戏 python飞机大战中的音频文件怎么改成MP3...

    怎么样用Python写飞机大战游戏 python开发飞机大战外星人游戏怎么弄双人模式新的一年,哪怕仍是一个人,也要活得像一支队伍,为自己的头脑和心灵招兵买马,不气馁,有召唤,爱自由. 主函数 impo ...

最新文章

  1. 索尼AI CEO:我们要让AI在30年内拿到诺贝尔奖
  2. 三阶魔方自动还原 vc实现
  3. 世界坐标系,相机坐标系和图像坐标系的转换(Python)
  4. AI机器人不认同人类语言 产生自己的交流方式 Facebook关闭了他们的人工智能系统...
  5. 中国网建SMS短信接口调用(java发送短信)
  6. Android Studio安装问题及填坑
  7. 【干货分享】流程DEMO-事务呈批表
  8. ffmpeg 纯静态编译,以及添加自定义库流程摘要
  9. 基于java银行ATM管理系统设计(含源文件)
  10. 音视频开发(12)---视频监控三大标准比较 ONVIF不负众望
  11. 计算仰角_41页最新全站仪测量方法及计算+图文解说,助你轻松掌握测量
  12. DCMTK3.5.4与3.6.0版本的区别
  13. Linux的基本操作
  14. MAC与PHY的接口GMII RGMII SGMII Serdes
  15. 屏蔽 NVIDIA 显卡
  16. 免费CMS哪个好用,老站长给大家推荐这几款CMS建站系统
  17. 基于51单片机的电子密码锁设计
  18. 一个帅哥到一个老头的历程
  19. Intel D435深度相机“No Frames Received!“问题
  20. 产品思维训练 | 以网易云和微信为例,产品迭代的依据是什么?

热门文章

  1. 云物大智题库--物联网
  2. VSO DownloaderV4.2.6.2软件介绍及使用方法
  3. Linux之进程间通信③——信号量(Semaphore)
  4. mysql随机生成中文地址_MySQL随机生成电话号码,邮箱和中文姓名sql
  5. eclipse Debug 初尝试 (09.10教师节(*^▽^*))
  6. 人工智能助力催收智能化、高效化
  7. 先进技术的研发和加快落地 细分赛道人工智能企业上市步伐加速
  8. STIL中的Spec
  9. 干货分享-刷票如此简单,一句js代码搞定
  10. 37.绘制文本DrawText、DrawTextEx、DRAWTEXTPARAMS 使用