⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 telligent.cpp

📁 九江麻将源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
                        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 + -