2015華爲軟件精英挑戰賽德州撲克之蒙特卡洛法模擬勝率

由於比賽500ms的時間限制,想要知道自己的牌力勝率是多大,我們採取了蒙特卡洛法,模擬對手的手牌,計算自己的勝率,依據勝率作出決策

經過幾次改進,該模擬算法可以在500ms以內完成,從而可以保證不超時

void sortCards(card mcard[], int num)
{
    int temp = 0,temp2;
    for (int i = 0; i < num; i++)
    for (int j = 0; j < num - i - 1; j++)
    {
        if (mcard[j].point < mcard[j + 1].point)
        {
            temp = mcard[j].point;
            mcard[j].point = mcard[j + 1].point;
            mcard[j + 1].point = temp;

            temp2=mcard[j].color;
            mcard[j].color=mcard[j+1].color;
            mcard[j+1].color=temp2;
        }
    }

}
void sortCardsColor(card mcard[], int num)
{
    int temp = 0,temp2;
    for (int i = 0; i < num; i++)
    for (int j = 0; j < num - i - 1; j++)
    {
        if (mcard[j].color < mcard[j + 1].color)
        {
            temp = mcard[j].point;
            mcard[j].point = mcard[j + 1].point;
            mcard[j + 1].point = temp;

            temp2=mcard[j].color;
            mcard[j].color=mcard[j+1].color;
            mcard[j+1].color=temp2;
        }
    }

}
void produceNumbersCard(card mcard[], int size =RANDSIZE)
{
    srand(time(NULL));

    for (int i = 0; i<size; i++)

        mcard[i].point = ((rand() % (14 - 2 + 1)) + 2);
    srand(time(NULL));
    for (int i = 0; i<size; i++)
        mcard[i].color = ((rand() % (4 - 1 + 1)) + 1);
}
bool isInHadCards(card newCard, card hadCard[],int hadCardSize)
{

     for (int i = 0; i < hadCardSize; i++)
     {
         if (newCard.point == hadCard[i].point&&newCard.color == hadCard[i].color)
         {
           return true;
         }
     }

    return false;
}

long calculTongHuaShun(card th[])
{

    if((th[0].point-th[4].point)==12)
        return 630000+11000000;   //A5432
    long temp=0;
    temp=th[0].point*100000+th[1].point*6000+th[2].point*400+th[3].point*20+th[4].point;
    return temp+11000000;
}

long calculSiTiao(card st[])
{

    if(st[0].point==st[1].point)  //四條在前,單牌在後88883;
        return st[0].point*400+st[4].point+10000000;
    else                         //四條在後,單牌在前52222;
        return st[1].point*400+st[0].point+10000000;
}

long calculLuHua(card Lh[])
{
    if(Lh[0].point==Lh[1].point&&Lh[1].point==Lh[2].point) //表示三條在前
        return Lh[0].point*400+Lh[3].point+9000000;
    else              //表示兩條在前
        return Lh[2].point*400+Lh[0].point+9000000;
}
long calculTongHua(card th[])
{
   long temp=0;
   temp=th[0].point*100000+th[1].point*6000+th[2].point*400+th[3].point*20+th[4].point;
   return temp+7000000;
}
long calculShunZi(card sz[])
{
    long temp=0;
    temp=sz[0].point*100000+sz[1].point*6000+sz[2].point*400+sz[3].point*20+sz[4].point;
    return temp+5000000;
}
long calculSanTiao(card sant[])
{
    int k=0;  //記錄第一個三條出現的位置
    for(int i=0;i<3;i++)
    {   //如果三張牌連續相等
        if(sant[i].point==sant[i+1].point&&sant[i+1].point==sant[i+2].point)
        {
           k=i;
        }
    }
    switch(k)
    {
    case 0: return sant[0].point*400+sant[3].point*20+sant[4].point+4000000;//55543
    case 1: return sant[1].point*400+sant[0].point*20+sant[4].point+4000000;//65553
    case 2: return sant[2].point*400+sant[0].point*20+sant[1].point+4000000;//76555
    }
}
long calculLiangDui(card Ld[])
{
    int fk=0,sk=0;  //分別用來記錄第一對與第二對的位置
    if(Ld[0].point==Ld[1].point)
        fk=0;
    else if(Ld[1].point==Ld[2].point)
        fk=1;
    if(Ld[2].point==Ld[3].point)
        sk=2;
    else if(Ld[3].point==Ld[4].point)
        sk=3;

    if(fk==0&&sk==2)   //66553
        return Ld[0].point*400+Ld[2].point*20+Ld[4].point+3000000;
    else if(fk==1&&sk==3)//76655
        return Ld[1].point*400+Ld[3].point*20+Ld[0].point+3000000;
    else                  //77566
        return Ld[0].point*400+Ld[3].point*20+Ld[2].point+3000000;
}
long calculYiDui(card yd[])
{
    int ydk=0;  //記錄一對的位置
    for(int i=0;i<4;i++)
    {
       if(yd[i].point==yd[i+1].point)
       {
           ydk=i;
           break;
       }
    }
    switch(ydk)
    {
    //77654
    case 0: return yd[0].point*6000+yd[2].point*400+yd[3].point*20+yd[4].point+2000000;
   //87754
    case 1: return yd[1].point*6000+yd[0].point*400+yd[3].point*20+yd[4].point+2000000;
    //98775
    case 2: return yd[2].point*6000+yd[0].point*400+yd[1].point*20+yd[4].point+2000000;
    //98766
    case 3: return yd[3].point*6000+yd[0].point*400+yd[1].point*20+yd[2].point+2000000;
    }
}
long calculGaoPai(card gp[])
{
    long temp=0;
    temp=gp[0].point*100000+gp[1].point*6000+gp[2].point*400+gp[3].point*20+gp[4].point;
    return temp;
}
long mycalcul7Card(card seven[])
{
    card tsc[7];
    for (int i = 0; i<7; i++)
    {
        tsc[i].point = seven[i].point;
        tsc[i].color = seven[i].color;
    }

    sortCards(tsc, 7);

    //是否有同花順
    card tTHS[5];
    int tempTHSpoint = 0, tempTHSsize = 1;
    card tempTHSFive[5];  //儲存已經找到的五張最大順子
    card tempTHS[7];
    {
        tempTHSpoint = tsc[0].point;
        tempTHS[0].point = tsc[0].point;
        tempTHS[0].color = tsc[0].color;
    }
    //去重 9987654.
    for (int i = 1; i<7; i++)
    {
        if (tempTHSpoint != tsc[i].point)
        {
            tempTHSpoint = tsc[i].point;
            tempTHS[tempTHSsize].point = tsc[i].point;
            tempTHS[tempTHSsize].color = tsc[i].color;
            tempTHSsize++;
        }
    }
    if (tempTHSsize >= 5) //表示去重之後還有至少5張牌
    {

        int j = 0;
        sortCards(tempTHS, tempTHSsize);
        //進行是否是順子除了A5432
        for (int i = 0; i <= tempTHSsize - 5; i++)
        {
            if (tempTHS[i].point == tempTHS[i + 1].point + 1\
                &&tempTHS[i + 1].point == tempTHS[i + 2].point + 1\
                &&tempTHS[i + 2].point == tempTHS[i + 3].point + 1\
                &&tempTHS[i + 3].point == tempTHS[i + 4].point + 1\
                )
            {
                for (j = i; j<i + 5; j++) //把這五張順子儲存下來
                {
                    tempTHSFive[j - i].point = tempTHS[j].point;
                    tempTHSFive[j - i].color = tempTHS[j].color;
                }
                //判斷這個順子是否是同花
                sortCardsColor(tempTHSFive, 5);
                if (tempTHSFive[0].color == tempTHSFive[1].color\
                    &&tempTHSFive[1].color == tempTHSFive[2].color\
                    &&tempTHSFive[2].color == tempTHSFive[3].color\
                    &&tempTHSFive[3].color == tempTHSFive[4].color)
                {
                    return calculTongHuaShun(tempTHSFive);
                }
                else
                    continue;

            }
        } //跳出for,表示沒有找到順子,繼續找是否有A5432
        sortCards(tempTHS, tempTHSsize);
        if (tempTHS[0].point == 14 && tempTHS[tempTHSsize - 1].point == 2\
            &&tempTHS[tempTHSsize - 2].point == 3\
            &&tempTHS[tempTHSsize - 3].point == 4\
            &&tempTHS[tempTHSsize - 4].point == 5\
            &&tempTHS[0].color == tempTHS[tempTHSsize - 1].color\
            &&tempTHS[tempTHSsize - 1].color == tempTHS[tempTHSsize - 2].color\
            &&tempTHS[tempTHSsize - 2].color == tempTHS[tempTHSsize - 3].color\
            &&tempTHS[tempTHSsize - 3].color == tempTHS[tempTHSsize - 4].color)
        {
            tempTHSFive[0].point = 14;
            tempTHSFive[0].color = tempTHS[0].color;
            tempTHSFive[1].point = 5;
            tempTHSFive[1].color = tempTHS[0].color;
            tempTHSFive[2].point = 4;
            tempTHSFive[2].color = tempTHS[0].color;
            tempTHSFive[3].point = 3;
            tempTHSFive[3].color = tempTHS[0].color;
            tempTHSFive[4].point = 2;
            tempTHSFive[4].color = tempTHS[0].color;
            return calculTongHuaShun(tempTHSFive);
        }
    }

    //是否有四條
    card tST[5];
    for (int i = 0; i<4; i++)
    {
        if (tsc[i].point == tsc[i + 1].point\
            &&tsc[i + 1].point == tsc[i + 2].point\
            &&tsc[i + 2].point == tsc[i + 3].point)
        {
            for (int j = i; j<i + 4; j++)
            {
                tST[j - i].point = tsc[j].point;
                tST[j - i].color = tsc[j].color;
            }
            if (i == 0)
            {

                tST[4].point = tsc[4].point;
                tST[4].color = tsc[4].color;
            }
            else
            {
                tST[4].point = tsc[0].point;
                tST[4].color = tsc[0].color;
            }
            sortCards(tST, 4);
            return calculSiTiao(tST);
        }
    }
    //是否有葫蘆
    card tHL[5];

    {
        //找出第一個三條4333222,5544333;
        int kHL = 0, HLflag = 0;
        for (int i = 0; i<5; i++)
        {
            if (tsc[i].point == tsc[i + 1].point&&\
                tsc[i + 1].point == tsc[i + 2].point)
            {
                for (int j = i; j<i + 3; j++)
                {
                    tHL[j - i].point = tsc[j].point;
                    tHL[j - i].color = tsc[j].color;
                }
                kHL = i;  //用來記錄三條的位置
                HLflag++; //表示找到了三條
                break;  //找到第一個三條就跳出循環 4333222;
            }
        }
        //找出第一個一對;4333222,5544333;6644433;
        for (int i = 0; i<6; i++)
        {
            if (tsc[i].point == tsc[i + 1].point\
                &&tsc[i].point != tsc[kHL].point)
            {
                for (int j = i; j<i + 2; j++)
                {
                    tHL[j - i + 3].point = tsc[j].point;
                    tHL[j - i + 3].color = tsc[j].color;
                }

                HLflag++;  //表示找到了一對
                break;
            }
        }
        if (HLflag == 2)
        {
            sortCards(tHL, 5);
            return  calculLuHua(tHL);
        }

    }
    //是否有同花
    card tTH[5];
    card tTH6[6];
    //@@@@@@@@@@@@@2
    card tTHC[7];
    for (int i = 0; i<7; i++)
    {
        tTHC[i].point = seven[i].point;
        tTHC[i].color = seven[i].color;
    }
    sortCardsColor(tTHC, 7); //分三種情況,5張同花,6張同花,7張同花
    //找到同花的數目
    int sameColorNumber = 1;
    for (int i = 0; i < 6; i++)
    {
        if (tTHC[i].color == tTHC[i + 1].color)
        {
            sameColorNumber++;
        }
        else
        {
            if (sameColorNumber < 5)
            {
                sameColorNumber = 1;
                continue;
            }
            else
            {
                break;
            }
        }
    }

    if (sameColorNumber == 5)
    {
        for (int i = 0; i < 3; i++)
        {
            if (tTHC[i].color == tTHC[i + 1].color\
                &&tTHC[i + 1].color == tTHC[i + 2].color\
                &&tTHC[i + 2].color == tTHC[i + 3].color\
                &&tTHC[i + 3].color == tTHC[i + 4].color)
            {
                for (int j = i; j < i + 5; j++)
                {
                    tTH[j - i].point = tTHC[j].point;
                    tTH[j - i].color = tTHC[j].color;
                }
                sortCards(tTH, 5);
                return calculTongHua(tTH);
            }
        }
    }
    else if (sameColorNumber == 6)
    {
        if (tTHC[0].color == tTHC[1].color)  //2222223
        {
            for (int ti = 0; ti < 6; ti++)
            {
                tTH6[ti].point = tTHC[ti].point;
                tTH6[ti].color = tTHC[ti].color;
            }
            sortCards(tTH6, 6);   //取出最大的5張同花
            for (int si = 0; si < 5; si++)
            {
                tTH[si].point = tTH6[si].point;
                tTH[si].color = tTH6[si].color;
            }
            return calculTongHua(tTH);
        }
        else
        {
            for (int ti = 1; ti < 7; ti++)
            {
                tTH6[ti - 1].point = tTHC[ti].point;
                tTH6[ti - 1].color = tTHC[ti].color;
            }
            sortCards(tTH6, 6);   //取出最大的5張同花
            for (int si = 0; si < 5; si++)
            {
                tTH[si].point = tTH6[si].point;
                tTH[si].color = tTH6[si].color;
            }
            return calculTongHua(tTH);
        }
    }
    else if (sameColorNumber == 7)
    {
        sortCards(tTHC, 7);
        for (int ki = 0; ki < 5; ki++)
        {
            tTH[ki].point = tTHC[ki].point;
            tTH[ki].color = tTHC[ki].color;
        }
        return calculTongHua(tTH);
    }


    //是否有順子
    card tSZ[5];
    int tempSZpoint = 0, tempSZsize = 1;
    card tempSZFive[5];
    card tempSZ[7];
    {
        tempSZpoint = tsc[0].point;
        tempSZ[0].point = tsc[0].point;
        tempSZ[0].color = tsc[0].color;
    }
    //去重 9987654.
    for (int i = 1; i<7; i++)
    {
        if (tempSZpoint != tsc[i].point)
        {
            tempSZpoint = tsc[i].point;
            tempSZ[tempSZsize].point = tsc[i].point;
            tempSZ[tempSZsize].color = tsc[i].color;
            tempSZsize++;
        }
    }
    if (tempSZsize >= 5) //表示去重之後還有至少5張牌
    {
        sortCards(tempSZ, tempSZsize);
        //進行是否是順子的判斷,除了A5432
        for (int i = 0; i <= tempSZsize - 5; i++)
        {
            if (tempSZ[i].point == tempSZ[i + 1].point + 1\
                &&tempSZ[i + 1].point == tempSZ[i + 2].point + 1\
                &&tempSZ[i + 2].point == tempSZ[i + 3].point + 1\
                &&tempSZ[i + 3].point == tempSZ[i + 4].point + 1)
            {
                for (int kk = i; kk<i + 5; kk++)
                {
                    tSZ[kk - i].point = tempSZ[kk].point;
                    tSZ[kk - i].color = tempSZ[kk].color;
                }
                sortCards(tSZ, 5);
                return calculShunZi(tSZ);
            }
        }//跳出for,尋找是否有A5432
        if (tempSZ[0].point == 14\
            &&tempSZ[tempSZsize - 1].point == 2\
            &&tempSZ[tempSZsize - 2].point == 3\
            &&tempSZ[tempSZsize - 3].point == 4\
            &&tempSZ[tempSZsize - 4].point == 5)
        {
            tempSZFive[0].point = 14;
            tempSZFive[0].color = tempSZ[0].color;
            tempSZFive[1].point = 5;
            tempSZFive[1].color = tempSZ[0].color;
            tempSZFive[2].point = 4;
            tempSZFive[2].color = tempSZ[0].color;
            tempSZFive[3].point = 3;
            tempSZFive[3].color = tempSZ[0].color;
            tempSZFive[4].point = 2;
            tempSZFive[4].color = tempSZ[0].color;
            return calculShunZi(tempSZFive);
        }

    }

    //是否有三條
    card tSST[5];
    int kSST = 0;
    for (int i = 0; i<5; i++)
    {
        if (tsc[i].point == tsc[i + 1].point\
            &&tsc[i + 1].point == tsc[i + 2].point)
        {
            kSST = i;//記錄三條的位置
            for (int j = i; j<i + 3; j++)
            {
                tSST[j - i].point = tsc[j].point;
                tSST[j - i].color = tsc[j].color;
            }
            switch (kSST)
            {
                //9998765
            case 0:tSST[3].point = tsc[3].point; tSST[3].color = tsc[3].color;
                tSST[4].point = tsc[4].point; tSST[4].color = tsc[4].color;
                break;
                //9888765
            case 1:tSST[3].point = tsc[0].point; tSST[3].color = tsc[0].color;
                tSST[4].point = tsc[4].point; tSST[4].color = tsc[4].color;
                break;
                //9877765,9876665,9876555;
            default:tSST[3].point = tsc[0].point; tSST[3].color = tsc[0].color;
                tSST[4].point = tsc[1].point; tSST[4].color = tsc[1].color;
                break;

            }
            sortCards(tSST, 5);
            return calculSanTiao(tSST);
        }
    }

    //是否有兩對
    card tLD[5];
    {
        int tmaxflag = 0, tminflag = 0;
        int tLDflag = 0;
        for (int i = 0; i<7; i++)
        {
            if (tsc[i].point == tsc[i + 1].point)  //找到第一個大對
            {
                tLDflag++;
                tmaxflag = i;
                for (int j = i; j<i + 2; j++)
                {
                    tLD[j - i].point = tsc[j].point;
                    tLD[j - i].color = tsc[j].color;
                }
                break;
            }

        }
        if (tLDflag == 1)  //找到了第一個大對
        {
            for (int m = tmaxflag + 2; m<7 - 1; m++)
            {
                if (tsc[m].point == tsc[m + 1].point) //找到第二個對子
                {
                    tLDflag++;
                    tminflag = m;
                    for (int jm = m; jm<m + 2; jm++)
                    {
                        tLD[jm - m + 2].point = tsc[jm].point;
                        tLD[jm - m + 2].color = tsc[jm].color;
                    }
                    break;
                }
            }
            if (tLDflag == 2) //表示找到了兩對
            {
                //提取出最大的單牌
                if (tminflag == 2 && tmaxflag == 0)  //9988765
                {
                    tLD[4].point = tsc[4].point;
                    tLD[4].color = tsc[4].color;
                }
                else if (tmaxflag == 0 && tminflag - tmaxflag >= 3)//9987765,9987655
                {
                    tLD[4].point = tsc[2].point;
                    tLD[4].color = tsc[2].color;
                }
                else  //9887765,9877665,deng
                {
                    tLD[4].point = tsc[0].point;
                    tLD[4].color = tsc[0].color;
                }

                sortCards(tLD, 5);
                return calculLiangDui(tLD);
            }
        }
    }
    //是否有一對
    card tYD[5];
    {
        for (int i = 0; i<6; i++)
        {
            if (tsc[i].point == tsc[i + 1].point) //找到一對
            {

                for (int j = i; j<i + 2; j++)
                {
                    tYD[j - i].point = tsc[j].point;
                    tYD[j - i].color = tsc[j].color;
                }
                switch (i)
                {
                    //9987654
                case 0:{
                           for (int jj = 2; jj<2 + 3; jj++)
                           {
                               tYD[jj].point = tsc[jj].point;
                               tYD[jj].color = tsc[jj].color;
                           }
                           break;
                }
                    //9887654
                case 1:{
                           tYD[2].point = tsc[0].point;
                           tYD[2].color = tsc[0].color;
                           for (int jj = 3; jj<3 + 2; jj++)
                           {
                               tYD[jj].point = tsc[jj].point;
                               tYD[jj].color = tsc[jj].color;
                           }
                           break;
                }
                    //9877654
                case 2:{
                           tYD[2].point = tsc[4].point;
                           tYD[2].color = tsc[4].color;
                           for (int jj = 0; jj<2; jj++)
                           {
                               tYD[jj + 3].point = tsc[jj].point;
                               tYD[jj + 3].color = tsc[jj].color;
                           }
                           break;
                }
                    //9876654,9876554,9876544;
                default:{
                            for (int jj = 0; jj<3; jj++)
                            {
                                tYD[jj + 2].point = tsc[jj].point;
                                tYD[jj + 2].color = tsc[jj].color;
                            }
                            break;
                }
                }

                sortCards(tYD, 5);
                return calculYiDui(tYD);
            }
        }
    }
    //高牌
    card tGP[5];
    for (int i = 0; i<5; i++)
    {
        tGP[i].point = tsc[i].point;
        tGP[i].color = tsc[i].color;
    }
    return calculGaoPai(tGP);

}
//用到全局變量ALLCard
double predictMyFlopWinRate(int livePeopleNumber)
{

    int flag;//記錄我與對手7張牌比較的結果
    //得到我的手牌加公牌
    card myFlop[7];
    for (int i = 0; i < 5; i++)
    {
        myFlop[i].point = ALLCard[i].point;
        myFlop[i].color = ALLCard[i].color;
    }

  //記錄已有的公牌與模擬出的轉牌與河牌
    card publicCard[5];
    for(int i=0;i<3;i++)
    {
        publicCard[i].point=ALLCard[i+2].point;
        publicCard[i].color=ALLCard[i+2].color;
    }
    //是否已模擬出轉牌與河牌的標記
    int TRflag=0;
    //先隨機出50000張牌;
    card mCard[RANDSIZE];
    produceNumbersCard(mCard,RANDSIZE);
    //分別儲存已模擬的對手個數,已有牌的張數,一個對手手牌的張數
    int tempPeopleNum = 0, hadCardSize = 5, twoCardSize = 0;
    int counter = 0, effctCardNum = 0;
    card oneCard, twoCard[2];
    card hadCard[16+3+2];  //最多8個人,16+3+2張牌
    for (int i = 0; i < 5; i++) //把我的手牌與公牌加入到hadCard裏面
    {
        hadCard[i].point = ALLCard[i].point;
        hadCard[i].color = ALLCard[i].color;
    }

    //儲存敵人的7張牌
    card enemyCard[7];
    int flag2=0;
    //在隨機出來的牌裏模擬敵人的牌
    for (int i = 0; i < RANDSIZE; i++)
    {
        oneCard = mCard[i];

        if (isInHadCards(oneCard, hadCard, hadCardSize))
        {

            continue;  //如果是已有的牌,則拋棄
        }
        else
        {
            //將一張牌放入twoCard中

            twoCard[twoCardSize].point = oneCard.point;
            twoCard[twoCardSize].color = oneCard.color;
            twoCardSize++;

            //把產生的牌放入hadCard中
            hadCard[hadCardSize].point = oneCard.point;
            hadCard[hadCardSize].color = oneCard.color;
            hadCardSize++;

            //如果只產生了一張合理的手牌,則繼續產生
            if (twoCardSize != 2)
                continue;
            else
            {
                if(TRflag==0)  //表示還沒有產生河牌與轉牌
                {
                    //加入到公牌裏
                    for(int mm=0;mm<2;mm++)
                    {
                        publicCard[mm+3].point=twoCard[mm].point;
                        publicCard[mm+3].color=twoCard[mm].color;
                    }
                    //加入到我的7張牌裏
                    for(int mm=0;mm<2;mm++)
                    {
                        myFlop[mm+5].point=twoCard[mm].point;
                        myFlop[mm+5].color=twoCard[mm].color;
                    }

                    twoCardSize=0;
                    //修改標誌,表示已模擬出轉牌與河牌
                    TRflag=1;
                    continue;  //再模擬兩張,作爲敵人的手牌
                }
                //表示已產生轉牌與河牌,則將產生的兩張牌作爲敵人的手牌
                tempPeopleNum++;  //產生了兩張合理的牌,則表示產生了一名對手的牌

                //將5張公牌加入到敵人的手牌裏
                for(int mj=0;mj<5;mj++)
                {
                    enemyCard[mj].point=publicCard[mj].point;
                    enemyCard[mj].color=publicCard[mj].color;
                }
                //將產生的兩張牌加入到敵人的牌裏
                for (int mi = 0; mi<2; mi++)
                {
                    enemyCard[mi + 5].point = twoCard[mi].point;
                    enemyCard[mi + 5].color = twoCard[mi].color;
                }
                twoCardSize = 0;

                //flag=compar7Card(myFlop,enemyCard);
                long m1=mycalcul7Card(myFlop);
                long m2=mycalcul7Card(enemyCard);
                if(m1>=m2)
                    flag=2;
                else
                     flag=0;



                //模擬的手牌數清零
                if (flag==0)  //敵人大
                {


                    effctCardNum++;
                    tempPeopleNum = 0;  //表示下一輪模擬開始

                    for (int jj = 5; jj< 16 + 3+2; jj++)
                    {
                        hadCard[jj].point = 0;
                        hadCard[jj].color = 0;
                    }
                    flag2=0;
                    hadCardSize = 5;
                    TRflag=0;  //將公牌裏面的河牌與轉牌去掉
                    continue;
                }
                else
                {
                     flag2=flag2+2; //test
                    if(tempPeopleNum!=livePeopleNumber) //還沒有模擬一輪
                        continue;
                    else
                    {

                        if(flag2==2*livePeopleNumber)//test
                        {
                            counter++;
                        }
                        tempPeopleNum=0;
                        effctCardNum++;  //模擬的輪數加一
                        for (int jm = 5; jm< 16 + 3+2; jm++) //已有的牌裏只保留我的手牌與公牌
                        {
                            hadCard[jm].point = 0;
                            hadCard[jm].color = 0;
                        }
                        flag2=0;//test
                        hadCardSize = 5;
                        TRflag=0;  //將公牌裏面的河牌與轉牌去掉
                        continue;

                    }

                }



            }

        }
    }
    return double(counter)/(double(effctCardNum));
}
double predictMyTurnWinRate(int livePeopleNumber)
{

   int flag;//記錄我與對手7張牌比較的結果
   //得到我的手牌加公牌加轉牌加河牌
   card myTurn[7];
   for (int i = 0; i < 6; i++)
   {
       myTurn[i].point = ALLCard[i].point;
       myTurn[i].color = ALLCard[i].color;
   }

 //記錄已有的公牌與模擬出河牌
   card publicCard[5];
   for(int i=0;i<4;i++)
   {
       publicCard[i].point=ALLCard[i+2].point;
       publicCard[i].color=ALLCard[i+2].color;
   }
   //是否已模擬出轉牌與河牌的標記
   int TRflag=0;
   //先隨機出50000張牌;
   card mCard[RANDSIZE];
   produceNumbersCard(mCard,RANDSIZE);
   //分別儲存已模擬的對手個數,已有牌的張數,一個對手手牌的張數
   int tempPeopleNum = 0, hadCardSize = 6, twoCardSize = 0;
   int counter = 0, effctCardNum = 0;
   card oneCard, twoCard[2];
   card hadCard[16+3+2+1];  //最多8個人,16+3+2+1張牌
   for (int i = 0; i < 6; i++) //把我的手牌與公牌加入到hadCard裏面
   {
       hadCard[i].point = ALLCard[i].point;
       hadCard[i].color = ALLCard[i].color;
   }

   //儲存敵人的7張牌
   card enemyCard[7];
   int flag2=0;
   //在隨機出來的牌裏模擬敵人的牌
   for (int i = 0; i < RANDSIZE; i++)
   {
       oneCard = mCard[i];

       if (isInHadCards(oneCard, hadCard, hadCardSize))
       {

           continue;  //如果是已有的牌,則拋棄
       }
       else
       {
           //將一張牌放入twoCard中

           twoCard[twoCardSize].point = oneCard.point;
           twoCard[twoCardSize].color = oneCard.color;
           twoCardSize++;

           //把產生的牌放入hadCard中
           hadCard[hadCardSize].point = oneCard.point;
           hadCard[hadCardSize].color = oneCard.color;
           hadCardSize++;

           //如果只產生了一張合理的手牌,則繼續產生
           if (twoCardSize != 2)
               continue;
           else
           {
               if(TRflag==0)  //表示還沒有產生河牌
               {
                   //取一張牌加入到公牌裏

                       publicCard[4].point=twoCard[0].point;
                       publicCard[4].color=twoCard[0].color;

                   //加入到我的7張牌裏

                       myTurn[6].point=twoCard[0].point;
                       myTurn[6].color=twoCard[0].color;


                   twoCardSize=0;
                   //修改標誌,表示已模擬出轉牌與河牌
                   TRflag=1;
                   continue;  //再模擬兩張,作爲敵人的手牌
               }
               //表示已產生轉牌與河牌,則將產生的兩張牌作爲敵人的手牌
               tempPeopleNum++;  //產生了兩張合理的牌,則表示產生了一名對手的牌

               //將5張公牌加入到敵人的手牌裏
               for(int mj=0;mj<5;mj++)
               {
                   enemyCard[mj].point=publicCard[mj].point;
                   enemyCard[mj].color=publicCard[mj].color;
               }
               //將產生的兩張牌加入到敵人的牌裏
               for (int mi = 0; mi<2; mi++)
               {
                   enemyCard[mi + 5].point = twoCard[mi].point;
                   enemyCard[mi + 5].color = twoCard[mi].color;
               }
               twoCardSize = 0;

               //flag=compar7Card(myTurn,enemyCard);
               long m1=mycalcul7Card(myTurn);
               long m2=mycalcul7Card(enemyCard);
               if(m1>=m2)
                   flag=2;
               else
                   flag=0;


               //模擬的手牌數清零
               if (flag==0)  //敵人大
               {


                   effctCardNum++;
                   tempPeopleNum = 0;  //表示下一輪模擬開始

                   for (int jj = 6; jj< 16 + 3+2+1; jj++)
                   {
                       hadCard[jj].point = 0;
                       hadCard[jj].color = 0;
                   }
                   flag2=0;
                   hadCardSize = 6;
                   TRflag=0;  //將公牌裏面的河牌與轉牌去掉
                   continue;
               }
               else
               {
                    flag2=flag2+2;
                   if(tempPeopleNum!=livePeopleNumber) //還沒有模擬一輪
                       continue;
                   else
                   {

                       if(flag2==2*livePeopleNumber)
                       {
                           counter++;
                       }
                       tempPeopleNum=0;
                       effctCardNum++;  //模擬的輪數加一
                       for (int jm = 6; jm< 16 + 3+2+1; jm++) //已有的牌裏只保留我的手牌與公牌
                       {
                           hadCard[jm].point = 0;
                           hadCard[jm].color = 0;
                       }
                       flag2=0;
                       hadCardSize = 6;
                       TRflag=0;  //將公牌裏面的河牌與轉牌去掉
                       continue;

                   }

               }



           }

       }
   }
   return double(counter)/(double(effctCardNum));
}
double getMyRiverWinRate(int livePeopleNumber)
{

   int flag;//記錄我與對手5張牌比較的結果
   //得到我的手牌加公牌加轉牌
   card myRiver[7];
   for (int i = 0; i < 7; i++)
   {
        myRiver[i].point = ALLCard[i].point;
        myRiver[i].color = ALLCard[i].color;
   }


   //先隨機出50000張牌;
   card mCard[RANDSIZE];
   produceNumbersCard(mCard,RANDSIZE);
   //分別儲存已模擬的對手個數,已有牌的張數,一個對手手牌的張數
   int tempPeopleNum = 0, hadCardSize = 7, twoCardSize = 0;
   int counter = 0, effctCardNum = 0;
   card oneCard, twoCard[2];
   card hadCard[16+3+1+1];  //最多8個人,16+3+2張牌
   for (int i = 0; i < 7; i++) //把我的手牌與公牌與轉牌加入到hadCard裏面
   {
       hadCard[i].point = ALLCard[i].point;
       hadCard[i].color = ALLCard[i].color;
   }
   //將公牌加入到對手的牌裏
   card enemyCard[7];
    int flag2=0;
   //在隨機出來的牌裏模擬敵人的牌
   for (int i = 0; i < RANDSIZE; i++)
   {
       oneCard = mCard[i];
       if (isInHadCards(oneCard, hadCard, hadCardSize))
       {
           continue;  //如果是已有的牌,則拋棄
       }
       else
       {
           //將一張牌放入twoCard中

           twoCard[twoCardSize].point = oneCard.point;
           twoCard[twoCardSize].color = oneCard.color;
           twoCardSize++;
           //把產生的牌放入hadCard中
           hadCard[hadCardSize].point = oneCard.point;
           hadCard[hadCardSize].color = oneCard.color;
           hadCardSize++;
           //如果只產生了一張合理的手牌,則繼續產生
           if (twoCardSize != 2)
               continue;
           else
           {
               tempPeopleNum++;  //產生了兩張合理的牌,則表示產生了一名對手的牌

               //把公牌放在敵人的手牌裏
               for (int j = 0; j < 5;j++)
               {
                   enemyCard[j].point = ALLCard[j + 2].point;
                   enemyCard[j].color = ALLCard[j + 2].color;
               }
               //將產生的兩張牌加入到敵人的牌裏
               for (int mi = 0; mi<2; mi++)
               {
                   enemyCard[mi + 5].point = twoCard[mi].point;
                   enemyCard[mi + 5].color = twoCard[mi].color;
               }

               //flag=compar7Card(myRiver,enemyCard);
               //!!!!!!!!!!!!!!
               long m1=mycalcul7Card(myRiver);
               long m2=mycalcul7Card(enemyCard);
               if(m1>=m2)
                   flag=2;
               else
                   flag=0;



               twoCardSize = 0;  //模擬的手牌數清零
               if (flag==0)  //敵人大
               {


                   effctCardNum++;
                   tempPeopleNum = 0;  //表示下一輪模擬開始

                   for (int jj = 7; jj< 16 + 3+1+1; jj++)
                   {
                       hadCard[jj].point = 0;
                       hadCard[jj].color = 0;
                   }
                   flag2=0;//test
                   hadCardSize = 7;
                   continue;
               }
               else
               {
                   flag2=flag2+2;
                   if(tempPeopleNum!=livePeopleNumber) //還沒有模擬一輪
                       continue;
                   else
                   {

                       if(flag2==2*livePeopleNumber)
                       {
                           counter++;
                       }
                       tempPeopleNum=0;
                       effctCardNum++;  //模擬的輪數加一
                       for (int jm = 7; jm< 16 + 3+1+1; jm++) //已有的牌裏只保留我的手牌與公牌
                       {
                           hadCard[jm].point = 0;
                           hadCard[jm].color = 0;
                       }
                       flag2=0;
                       hadCardSize = 7;
                       continue;

                   }

               }



           }

       }
   }

   return double(counter)/(double(effctCardNum));

}

據實踐。模擬3000次左右,就已經可以穩定下來,再增加模擬次數,也沒什麼意義

發佈了35 篇原創文章 · 獲贊 5 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章