由於比賽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次左右,就已經可以穩定下來,再增加模擬次數,也沒什麼意義