传送门
解析:
这是一个大家应该都van♂van♂van♂过的游戏(没玩过没关系,题目描述还是够清晰的了)。
所以整理一下思路,模拟题肯定要理清楚思路再下手,不然手忙脚乱很容易出错。
我分享一下我的思路:
首先这道模拟的主要对象就是玩家,所以我们可以封装一个结构体来实现玩家的各种操作。
发牌&补牌
首先是发牌,我们可以用一个flagflagflag记录这次是否是发的第一轮的庄家,然后额外发一张牌。
领取新的牌可以用一个函数nxtcardnxtcardnxtcard来实现。
至于发牌怎么处理,由于题目要求不能拆对子和炸弹,所以我们直接用四个setsetset记录不同种类(单牌,对子,炸弹,氢弹)目前有哪些牌可以用。
我们可以用一个insertinsertinsert函数来实现新摸牌的操作,注意特判双王的情况。
新加的牌就是看它能否和原来的牌再凑一个更大的牌型。
头家出牌:
这个直接按照题意找一下什么牌能出就行了。
就是代码里面的gofirstgofirstgofirst函数。
局中拼牌:
首先优先考虑碰的操作,判断是否是单牌,如果是,就在其他玩家手里找对应的对子,注意碰完之后为了方便,lastcardlastcardlastcard的类型最好变成炸弹。
然后就是普通的拼大小。
这个可以直接用setsetset来一个upper_bound,然后考虑出炸弹,注意要考虑原本就是炸弹的情况。
游戏结束:
这个先判牌堆里面还有没有牌,然后判玩家手里还有没有就行了。
Detail:
1.注意时刻要更新玩家目前的手牌数,由于我是直接用牌的种类(单牌,对子,炸弹,氢弹)来判断出的牌数,所以要特殊处理一下双王的情况。
2.碰完之后还有一个情况需要处理,就是下家的改变,我就是这个写掉了两个字符就WAWAWA了几发。
接下来就是个人的耐心,细致和毅力以及码力的比拼了。
代码(无调试代码)(下面有一份有调试痕迹的):
#include<bits/stdc++.h>
using namespace std;
#define re register
#define cs const
typedef pair<int,int> pii;
#define single type[0]
#define pair type[1]
#define boom type[2]
#define bigboom type[3]
map<char,int> val;
char sss[1000],*cur=sss;
inline int nxtcard(){return val[*(cur++)];}
inline bool nocard(){return val[*cur]==0;}
inline bool isking(int card){
return card==13||card==14;
}
inline int anotherking(int king){
return 27-king;
}
inline int cntcard(cs pii &a){
if(a.second!=2)return a.second+1;
if(a.first==13||a.first==14)return 2;
else return 3;
}
bool flag=true;
struct players{
int now;
set<int> type[4];
inline void insert(int card){//新摸一张
++now;
for(int re i=2;~i;--i){
if(type[i].find(card)!=type[i].end()){
type[i+1].insert(card);
type[i].erase(card);
return;
}
}
if(isking(card)){
if(single.find(anotherking(card))!=single.end()){
single.erase(anotherking(card));
boom.insert(14);
}
else single.insert(card);
}
else{
single.insert(card);
}
}
inline void init(){//补牌 or 初始摸牌
while(now<5){
int card=nxtcard();
if(card==0)return;
insert(card);
}
if(flag){
flag=false;
int card=nxtcard();
if(card)insert(card);
}
}
inline pii gofirst(){//第一个出牌
if(now==0)return make_pair(0,0);
if(!pair.empty()&&*pair.begin()!=val['7']){
int card=*pair.begin();
pair.erase(pair.begin());
now-=2;
return make_pair(card,1);
}
if(!single.empty()){
int card=*single.begin();
single.erase(single.begin());
now-=1;
return make_pair(card,0);
}
if(!pair.empty()&&*pair.begin()==val['7']){
int card=*pair.begin();
pair.erase(pair.begin());
now-=2;
return make_pair(card,1);
}
if(!boom.empty()){
int card=*boom.begin();
boom.erase(boom.begin());
if(card!=14&&card!=13)now-=3;
else now-=2;
return make_pair(card,2);
}
if(!bigboom.empty()){
int card=*bigboom.begin();
bigboom.erase(bigboom.begin());
now-=4;
return make_pair(card,3);
}
}
inline pii peng(cs pii &a){
if(pair.find(a.first)!=pair.end()){
pair.erase(a.first);now-=2;
return make_pair(a.first,1);
}
return make_pair(0,0);
}
inline pii compete(cs pii &cd){
int ty=cd.second;
int card=cd.first;
set<int>::iterator it=type[ty].upper_bound(card);
if(it!=type[ty].end()){
card=*it;
type[ty].erase(it);
now-=cntcard(make_pair(card,ty));
return make_pair(card,ty);
}
for(int re i=max(ty+1,2);i<=3;++i){
if(!type[i].empty()){
card=*type[i].begin();
type[i].erase(type[i].begin());
now-=cntcard(make_pair(card,i));
return make_pair(card,i);
}
}
return make_pair(0,0);
}
inline bool empty(){return now==0;}
}player[4];
int score[4];
int n,lastwinner=0,totcard;
inline bool gameend(){
if(!nocard())return false;
for(int re i=0;i<n;++i)if(player[i].empty())return true;
return false;
}
signed main(){
{//权值打表
val[' ']=0;
val[0]=0;
val['\n']=0;
val['4']=1;
val['6']=2;
val['8']=3;
val['9']=4;
val['X']=5;
val['J']=6;
val['Q']=7;
val['K']=8;
val['A']=9;
val['3']=10;
val['2']=11;
val['5']=12;
val['F']=13;
val['G']=14;
val['7']=15;
}
scanf("%d",&n);
scanf("%s",sss);
while(true){
totcard=0;
for(int re i=0;i<n;++i)player[(i+lastwinner)%n].init();
if(gameend())break;
pii lastcard=player[lastwinner].gofirst();
totcard+=cntcard(lastcard);
if(lastcard.second==0){
for(int re i=(lastwinner+1)%n;i!=lastwinner;i=(i+1)%n){
pii nowcard=player[i].peng(lastcard);
if(nowcard.first==0)continue;
lastcard=nowcard;
totcard+=cntcard(nowcard);
lastwinner=i;
lastcard.second=2;
break;
}
}
for(int re i=(lastwinner+1)%n;i!=lastwinner;i=(i+1)%n){
pii nowcard=player[i].compete(lastcard);
if(nowcard.first==0)continue;
lastwinner=i;
totcard+=cntcard(nowcard);
lastcard=nowcard;
if(lastcard.second==0){
for(int re j=(lastwinner+1)%n;j!=lastwinner;j=(j+1)%n){
pii nowcard=player[j].peng(lastcard);
if(nowcard.first==0)continue;
lastcard=nowcard;
totcard+=cntcard(nowcard);
i=lastwinner=j;
lastcard.second=2;
break;
}
}
}
score[lastwinner]+=totcard;
}
for(int re i=0;i<n;++i)printf("%d\n",score[i]+player[i].now);
return 0;
}
代码(保留调试痕迹):
#include<bits/stdc++.h>
using namespace std;
#define re register
#define cs const
typedef pair<int,int> pii;
#define single type[0]
#define pair type[1]
#define boom type[2]
#define bigboom type[3]
map<char,int> val;
char sss[1000],*cur=sss;
inline int nxtcard(){return val[*(cur++)];}
inline bool nocard(){return val[*cur]==0;}
inline bool isking(int card){
return card==13||card==14;
}
inline int anotherking(int king){
return 27-king;
}
inline int cntcard(cs pii &a){
if(a.second!=2)return a.second+1;
if(a.first==13||a.first==14)return 2;
else return 3;
}
bool flag=true;
struct players{
int now;
set<int> type[4];
inline void insert(int card){//新摸一张
++now;
for(int re i=2;~i;--i){
if(type[i].find(card)!=type[i].end()){
type[i+1].insert(card);
type[i].erase(card);
return;
}
}
if(isking(card)){
if(single.find(anotherking(card))!=single.end()){
single.erase(anotherking(card));
boom.insert(14);
}
else single.insert(card);
}
else{
single.insert(card);
}
}
inline void init(){//补牌 or 初始摸牌
while(now<5){
int card=nxtcard();
if(card==0)return;
insert(card);
}
if(flag){
flag=false;
int card=nxtcard();
if(card)insert(card);
}
}
inline pii gofirst(){//第一个出牌
if(now==0)return make_pair(0,0);
if(!pair.empty()&&*pair.begin()!=val['7']){
int card=*pair.begin();
pair.erase(pair.begin());
now-=2;
return make_pair(card,1);
}
if(!single.empty()){
int card=*single.begin();
single.erase(single.begin());
now-=1;
return make_pair(card,0);
}
if(!pair.empty()&&*pair.begin()==val['7']){
int card=*pair.begin();
pair.erase(pair.begin());
now-=2;
return make_pair(card,1);
}
if(!boom.empty()){
int card=*boom.begin();
boom.erase(boom.begin());
if(card!=14&&card!=13)now-=3;
else now-=2;
return make_pair(card,2);
}
if(!bigboom.empty()){
int card=*bigboom.begin();
bigboom.erase(bigboom.begin());
now-=4;
return make_pair(card,3);
}
}
inline pii peng(cs pii &a){
if(pair.find(a.first)!=pair.end()){
pair.erase(a.first);now-=2;
return make_pair(a.first,1);
}
return make_pair(0,0);
}
inline pii compete(cs pii &cd){
int ty=cd.second;
int card=cd.first;
set<int>::iterator it=type[ty].upper_bound(card);
if(it!=type[ty].end()){
card=*it;
type[ty].erase(it);
now-=cntcard(make_pair(card,ty));
return make_pair(card,ty);
}
for(int re i=max(ty+1,2);i<=3;++i){
if(!type[i].empty()){
card=*type[i].begin();
type[i].erase(type[i].begin());
now-=cntcard(make_pair(card,i));
return make_pair(card,i);
}
}
return make_pair(0,0);
}
inline bool empty(){return now==0;}
}player[4];
int score[4];
int n,lastwinner=0,totcard;
inline bool gameend(){
if(!nocard())return false;
for(int re i=0;i<n;++i)if(player[i].empty())return true;
return false;
}
string typ[4]={(string)"单牌",(string)"对子",(string)"炸弹",(string)"氢弹"};
char car[50]={'?','4','6','8','9','X','J','Q','K','A','3','2','5','F','G','7'};
inline void debug(int play,cs pii &card){
cerr<<"player "<<lastwinner<<" 出牌 "<<typ[card.second]<<" "<<car[card.first];
cerr<<" 剩余手牌 "<<player[play].now<<" 张\n";
}
inline void Debug(){
for(int re i=0;i<n;++i){
cerr<<"player "<<i<<" :";
if(player[i].empty()){
cerr<<"\nno cards\n";
continue;
}
for(int re j=0;j<4;++j){
if(player[i].type[j].empty())continue;
cerr<<"\n"<<typ[j]<<" : ";
for(set<int>::iterator it=player[i].type[j].begin();it!=player[i].type[j].end();++it){
cerr<<car[*it]<<" ";
}
cerr<<"\n";
}
}
}
signed main(){
{//权值打表
val[' ']=0;
val[0]=0;
val['\n']=0;
val['4']=1;
val['6']=2;
val['8']=3;
val['9']=4;
val['X']=5;
val['J']=6;
val['Q']=7;
val['K']=8;
val['A']=9;
val['3']=10;
val['2']=11;
val['5']=12;
val['F']=13;
val['G']=14;
val['7']=15;
}
scanf("%d",&n);
scanf("%s",sss);
while(true){
cerr<<"\n\n A New Round :\n";
totcard=0;
for(int re i=0;i<n;++i)player[(i+lastwinner)%n].init();
Debug();
if(gameend())break;
pii lastcard=player[lastwinner].gofirst();
debug(lastwinner,lastcard);
totcard+=cntcard(lastcard);
if(lastcard.second==0){
for(int re i=(lastwinner+1)%n;i!=lastwinner;i=(i+1)%n){
pii nowcard=player[i].peng(lastcard);
if(nowcard.first==0)continue;
lastcard=nowcard;
totcard+=cntcard(nowcard);
lastwinner=i;
cerr<<"碰 ",debug(lastwinner,lastcard);
lastcard.second=2;
break;
}
}
for(int re i=(lastwinner+1)%n;i!=lastwinner;i=(i+1)%n){
pii nowcard=player[i].compete(lastcard);
if(nowcard.first==0)continue;
lastwinner=i;
totcard+=cntcard(nowcard);
lastcard=nowcard;
debug(lastwinner,lastcard);
if(lastcard.second==0){
for(int re j=(lastwinner+1)%n;j!=lastwinner;j=(j+1)%n){
pii nowcard=player[j].peng(lastcard);
if(nowcard.first==0)continue;
lastcard=nowcard;
totcard+=cntcard(nowcard);
i=lastwinner=j;
cerr<<"碰 ",debug(lastwinner,lastcard);
lastcard.second=2;
break;
}
}
}
cerr<<"player "<<lastwinner<<" get "<<totcard<<" scores\n";
score[lastwinner]+=totcard;
// Debug();
}
for(int re i=0;i<n;++i){
score[i]+=player[i].now;
}
for(int re i=0;i<n;++i){
printf("%d\n",score[i]);
}
return 0;
}