📄 telligent.cpp
字号:
wantto=nothing;
}
for(j=0;j<3;j++)
{
zuhand.takemj(zuhand.find(mja[i]));
}
if(mja[i]!=painewget)
{
zuhand.takemj(zuhand.find(mja[i]));
zuhand.insertmj(painewget);
}
painewget=mj;
sort();
}
static mjpaizu GetRidOfShunKe(mjpai* mj,int c,bool forward) //将一副牌中顺刻去掉
{ //返回剩下的牌,forward表示向前还是向后
vector<bool> selected;
int i;
for (i=0;i<c;i++)
selected.push_back(false);
mjpaizu zu;
int j,k,i_min,i_max,i_mid;
if(forward)
for(i=0;i<c;i++){
if(selected[i])continue;
for(j=i+1;j<c;j++){
if(i==j||selected[j])continue;
for(k=j+1;k<c;k++){
if(i==k||j==k||selected[k])continue;
i_max=0;i_min=100;
i_max=max(mj[i],max(mj[j],mj[k]));
i_min=min(mj[i],min(mj[j],mj[k]));
i_mid=(i_max+i_min)/2;
if(mj[i]==mj[j]&&mj[i]==mj[k]) //刻子
;
else if(i_max-i_min==2&&(mj[i]==i_mid||mj[j]==i_mid||mj[k]==i_mid))//顺子
;
else
continue;
selected[i]=selected[j]=selected[k]=true;
}
}
if(!selected[i]) zu.insertmj(mj[i]);
}
else
for(i=c-1;i>=0;--i){
if(selected[i])continue;
for(j=i-1;j>=0;j--){
if(i==j||selected[j])continue;
for(k=j-1;k>=0;k--){
if(i==k||j==k||selected[k])continue;
i_max=0;i_min=100;
i_max=max(mj[i],max(mj[j],mj[k]));
i_min=min(mj[i],min(mj[j],mj[k]));
i_mid=(i_max+i_min)/2;
if(mj[i]==mj[j]&&mj[i]==mj[k]) //刻子
;
else if(i_max-i_min==2&&(mj[i]==i_mid||mj[j]==i_mid||mj[k]==i_mid))//顺子
;
else
continue;
selected[i]=selected[j]=selected[k]=true;
}
}
if(!selected[i]) zu.insertmj(mj[i]);
}
return zu;
}
static mjpaizu discard_(mjpai* mj,int c)
{
assert(c%3 == 2);
int i;
mjpaizu canDiscard,canDiscard1;
mishel(mj,c);
for(i=c-1;i>0;i--) //返回单个的'字'
if(mj[i].iszi() && mj[i]!=mj[i-1])
return canDiscard.insertmj(mj[i]),canDiscard;
int j,k,i_min,i_max,i_mid;
//下面份2次搜索,从2个方向,除去3张相连的牌(刻、顺),把剩下的放进canDiscard
canDiscard1=GetRidOfShunKe(mj,c,true);
canDiscard=GetRidOfShunKe(mj,c,false) ;
//现在有了 canDiscard 和 temp 两幅由相反方向处理后得到的牌,分别处理它们
//然后取剩下的牌数较少的那副
//先处理canDiscard
canDiscard.sort();
for(i=0;i<canDiscard.getcount();i++)
{
int c;
mjpai temp=canDiscard.getmj(i);
c=count(canDiscard.begin(),canDiscard.end(),temp);
assert(c>=1&&c<=2);
if(c==2)
{
bool bGap1;//标志 是 344 334型 还是 244 224型
//去掉 xyy型的牌 445 335
if(i-1>=0 && ((bGap1=(canDiscard.getmj(i-1)==temp-1)) || canDiscard.getmj(i-1)==temp-2)
&& canDiscard.getcount()>3)//保证剩下至少1张
{
canDiscard.takemj(i);
canDiscard.takemj(canDiscard.find(temp));
canDiscard.takemj(canDiscard.find(bGap1?(temp-1):(temp-2)));
i=-1;
continue;
}
//去掉 xxy型的牌 112 113
if(i+2<canDiscard.getcount()
&& ((bGap1=(canDiscard.getmj(i+2)==temp+1)) || canDiscard.getmj(i+2)==temp+2)
&& canDiscard.getcount()>3)
if(count(canDiscard.begin(),canDiscard.end(),bGap1?(temp+1):(temp+2))==1)
{
canDiscard.takemj(i);
canDiscard.takemj(canDiscard.find(temp));
canDiscard.takemj(canDiscard.find(bGap1?(temp+1):(temp+2)));
i=-1;
continue;
}
}
//去掉 xx型的牌 55 66
if(c==2 && canDiscard.getcount()>2)
{
canDiscard.takemj(i);
canDiscard.takemj(canDiscard.find(temp));
i=-1;
continue;
}
if(c==2) ++i;
}
//现在都是单张,如果有不靠的牌,就把 靠(12 13)的牌去掉
bool hasBukao=false;
for(i=0;i<canDiscard.getcount();i++)
{
mjpai temp=canDiscard.getmj(i);
assert(count(canDiscard.begin(),canDiscard.end(),temp)==1
||canDiscard.getcount()==2);//都是单张
if((i-1>=0 && (canDiscard.getmj(i-1)-temp>2||temp-canDiscard.getmj(i-1)>2))
||(i+1<canDiscard.getcount() &&(canDiscard.getmj(i+1)-temp>2||temp-canDiscard.getmj(i+1)>2)))
hasBukao=true;
}
if(hasBukao) for(i=0;i<canDiscard.getcount();i++)
{
mjpai temp=canDiscard.getmj(i);
if(i+1<canDiscard.getcount()&& canDiscard.getcount()>2
&& temp-canDiscard.getmj(i+1)<=2 && canDiscard.getmj(i+1)-temp<=2)
{
mjpai temp1=canDiscard.getmj(i+1);
canDiscard.takemj(i);
canDiscard.takemj(canDiscard.find(temp1)); //取2张
i=-1;//从头
}
}
//对temp 进行同样处理
mjpaizu temp1=canDiscard;
canDiscard=canDiscard1;
canDiscard.sort();
for(i=0;i<canDiscard.getcount();i++)
{
int c;
mjpai temp=canDiscard.getmj(i);
c=count(canDiscard.begin(),canDiscard.end(),temp);
assert(c>=1&&c<=2);
if(c==2)
{
bool bGap1;//标志 是 344 334型 还是 244 224型
//去掉 xyy型的牌 445 335
if(i-1>=0 && ((bGap1=(canDiscard.getmj(i-1)==temp-1)) || canDiscard.getmj(i-1)==temp-2)
&& canDiscard.getcount()>3)//保证剩下至少1张
{
canDiscard.takemj(i);
canDiscard.takemj(canDiscard.find(temp));
canDiscard.takemj(canDiscard.find(bGap1?(temp-1):(temp-2)));
i=-1;
continue;
}
//去掉 xxy型的牌 112 113
if(i+2<canDiscard.getcount()
&& ((bGap1=(canDiscard.getmj(i+2)==temp+1)) || canDiscard.getmj(i+2)==temp+2)
&& canDiscard.getcount()>3)
if(count(canDiscard.begin(),canDiscard.end(),bGap1?(temp+1):(temp+2))==1)
{
canDiscard.takemj(i);
canDiscard.takemj(canDiscard.find(temp));
canDiscard.takemj(canDiscard.find(bGap1?(temp+1):(temp+2)));
i=-1;
continue;
}
}
//去掉 xx型的牌 55 66
if(c==2 && canDiscard.getcount()>2)
{
canDiscard.takemj(i);
canDiscard.takemj(canDiscard.find(temp));
i=-1;
continue;
}
if(c==2) ++i;
}
//现在都是单张,如果有不靠的牌,就把 靠(12 13)的牌去掉
hasBukao=false;
for(i=0;i<canDiscard.getcount();i++)
{
mjpai temp=canDiscard.getmj(i);
assert(count(canDiscard.begin(),canDiscard.end(),temp)==1
||canDiscard.getcount()==2);//都是单张
if((i-1>=0 && (canDiscard.getmj(i-1)-temp>2||temp-canDiscard.getmj(i-1)>2))
||(i+1<canDiscard.getcount() &&(canDiscard.getmj(i+1)-temp>2||temp-canDiscard.getmj(i+1)>2)))
hasBukao=true;
}
if(hasBukao) for(i=0;i<canDiscard.getcount();i++)
{
mjpai temp=canDiscard.getmj(i);
if(i+1<canDiscard.getcount()&& canDiscard.getcount()>2
&& temp-canDiscard.getmj(i+1)<=2 && canDiscard.getmj(i+1)-temp<=2)
{
mjpai temp1=canDiscard.getmj(i+1);
canDiscard.takemj(i);
canDiscard.takemj(canDiscard.find(temp1)); //取2张
i=-1;//从头
}
}
return canDiscard.getcount()>temp1.getcount()?temp1:canDiscard;
}
mjpai man::discard() //电脑出牌方法的核心
{
mjpai mj[14];
int c,i;
assert(painewget!=0);
if(Form1->mjots.getcount()<10 && wantto==nothing && Form1->difficult==3)//前阶段判断大体的3个方向
{ //难度3 才有
bool flag;
if(zuhand.getcount()-numofse(wan)<=5||(zuhand.getcount()-numofse(wan)==6
&&(Form1->paishu[2]-Form1->avepaishu>=20-6||Form1->paishu[4]-Form1->avepaishu>=15-6)))
{ //六张的时候如果要打一色,必须是一色的分数比较高
flag=false;
//在已经亮出的牌中找,如果不符合要打的一色的牌,就算了,不打一色
for(int i=0;i<zushowed.getkuaicount();i++)
if(zushowed.whatcolor(i)==2||zushowed.whatcolor(i)==3)
flag=true;
if(!flag)
{
se=wan; wantto=yise;
}
}
if(zuhand.getcount()-numofse(tiao)<=5 || (zuhand.getcount()-numofse(tiao)==6
&&(Form1->paishu[2]-Form1->avepaishu>=20-6||Form1->paishu[4]-Form1->avepaishu>=15-6))) {
flag=false;
for(int i=0;i<zushowed.getkuaicount();i++)
if(zushowed.whatcolor(i)==1||zushowed.whatcolor(i)==3)
flag=true;
if(!flag)
{
se=tiao; wantto=yise;
}
}
if(zuhand.getcount()-numofse(bing)<=5 || (zuhand.getcount()-numofse(bing)==6
&&(Form1->paishu[2]-Form1->avepaishu>=20-6||Form1->paishu[4]-Form1->avepaishu>=15-6))) {
flag=false;
for(int i=0;i<zushowed.getkuaicount();i++)
if(zushowed.whatcolor(i)==2||zushowed.whatcolor(i)==1)
flag=true;
if(!flag)
{
se=bing; wantto=yise;
}
}
if(zuhand.getcount()-numofdui()*2<=5 || (zuhand.getcount()-numofdui()*2==6
&&(Form1->paishu[6]-Form1->avepaishu>=20-6||Form1->paishu[8]-Form1->avepaishu>=20-6)))
{
if(zuhand.getcount()==13)
wantto=dui;
else wantto=pengpeng;
}
}
c=zuhand.getcount();
for(i=0;i<c;i++)
mj[i]=zuhand.getmj(i);
if(Form1->difficult==3){ //难度3 才有
mjpaizu zu;
switch(wantto) //3大方向
{
case yise:
if(yise_(mj,c,painewget).getcount() > 0)
{
zu=(mjpaizu&)yise_(mj,c,painewget);
for(int i=0;i<zu.getcount();i++)
if(Form1->mjots.find(zu.getmj(i)) > 0)
return zu.getmj(i);
return zu.getmj(0);
}
break;
case dui:
zu= (mjpaizu&)dui_(mj,c,painewget);
for(int i=0;i<zu.getcount();i++)
if(Form1->mjots.find(zu.getmj(i)) > 0)
return zu.getmj(i);
return zu.getmj(0);
case pengpeng:
zu= (mjpaizu&)pengpeng_(mj,c,painewget);
for(int i=0;i<zu.getcount();i++)
if(Form1->mjots.find(zu.getmj(i)) > 0)
return zu.getmj(i);
return zu.getmj(0);
}
}
int n[14];
if(ting(mj,c).getcount()>0 && Form1->difficult>=2) //已经听牌? 出一张能听最多的
{ //难度2以上
isting=true;
int max=ting(mj,c).getcount();
for(int j=0;j<max;j++) //除去这么多可以和的牌中已经出完的
if(Form1->mjots.find(ting(mj,c).getmj(j))==4)
max--;
int index=-1,temp;
for(i=0;i<c;i++)
{
temp=mj[i]; mj[i]=painewget;
n[i]=ting(mj,c).getcount();
for(int j=0;j<n[i];j++)
if(Form1->mjots.find(ting(mj,c).getmj(j))==4) //除去这么多可以和的牌中已经出完的
n[i]--;
if(n[i]>max)
{max=n[i];index=i;}
mj[i]=temp;
}
if(Form1->mjots.getcount()>8*4&&Form1->difficult==3) //如果到了结尾,注意出牌,没大过的不出
{
int m=max;
while(m>0){
for(int j=0;j<c;j++)
if(m==n[j]&&Form1->mjots.find(mj[j])>0)
return mj[j];
m--; //减少m 再搜索
}
}
if(index==-1) return painewget;
else return mj[index];
}
if(Form1->difficult >= 2) //难度二以上 //打出不靠的 和能听的
{
int temp;
mjpaizu zu;
if(bukao(mj,c,painewget)) zu.insertmj(painewget);//先对painewget处理
for(i=0;i<c;i++)
{
temp=mj[i]; mj[i]=painewget;
if(bukao(mj,c,temp)) zu.insertmj(temp); //有可能要出的,存到zu里
if(ting(mj,c).getcount()>0)
{zu.insertmj(temp);isting=true;}
mj[i]=temp;
}
if(Form1->mjots.getcount()>8*4&&Form1->difficult==3)
{for(i=0;i<zu.getcount();i++)
if(Form1->mjots.find(zu.getmj(i))>0)
return zu.getmj(i);
}
if(zu.getcount()>0) //实在出不去 就出第1张
return zu.getmj(0);
}
//下面是还未听牌的时候的常规打法
mj[c++]=painewget;
mjpaizu zu=discard_(mj,c);
#ifndef NLABEL
Form1->Label9->Caption="";
for(int i=0;i<zu.getcount();i++)
Form1->Label9->Caption=Form1->Label9->Caption+AnsiString(zu.getmj(i))+" ";
#endif
if(Form1->mjots.getcount()>8*4 && Form1->difficult>=2)//打了8*4张以后且难度为2,就得拣熟牌打
{for(i=0;i<zu.getcount();i++)
if(Form1->mjots.find(zu.getmj(i))>0)
return zu.getmj(i);
}
if(zu.getcount()>0) return zu.getmj(0);
else return mj[0];
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -