我开始自己学习C语言,并决定构建计算扑克股票的程序。我试图用蒙特卡罗计算公平,但我得到错误的结果。用于计算扑克股票的蒙特卡罗方法
所以这里是一个例子:我拿着JsTs(黑桃杰克和黑桃10)。我有两个对手分配特定的手牌。第一个对手只能使用AA(任何Ace-Ace口袋,总共6种不同组合),第二个对手使用KK +(任何Ace-Ace或King-King口袋)。所以计算过程从随机选择一个范围开始(对于对手1这总是AA)。然后我决定在该范围内的不同组合(Ah Ac,Ah Ad,Ah As ...等)并随机选择范围内的其中一个组合。所以我这样做是为了对手。然后我随机选择五张棋盘牌并评估玩家手牌和对手牌。然后我看看我是否赢或平局并保持结果。
所以我这样做了1000万次,我的股本达到了20.5%,但应该是19.1%。这里是我的代码的main()函数:
int main()
{
randctx rctx;
Deck[4][13];
randinit(&rctx, TRUE);
numberOfOpponents = 2;
//opponent ranges selected
rangeIsSelected[0][0]= 1;
rangeIsSelected[1][0]= 1;
rangeIsSelected[1][14]= 1;
//player cards
Player_Card_Flush[0] = 0;
Player_Card_Rank[0] = 8;
Player_Card_Flush[1] = 0;
Player_Card_Rank[1] = 9;
//insert player cards to dealt cards
Deck[Player_Card_Flush[0]][Player_Card_Rank[0]] = 1;
Deck[Player_Card_Flush[1]][Player_Card_Rank[1]] = 1;
checkForErrors(0);
if (impossibleError==1) {
printf("Impossible to calculate equity");
return;
}
gamesSimulated = 0;
totalTies = 0;
totalWins = 0;
int opponentToBeDealt = 0;
//let's see what ranges are selected by opponents
for (int i=0; i<numberOfOpponents; i++) {
findSelectedRanges(i);
}
//beginning of Monte Carlo method
while (gamesSimulated<maxTrials) {
int b = 0;
int opponentsDealt = 0;
//randomly select hand for opponents
while (opponentsDealt<numberOfOpponents) {
opponentCardsForMonteCarlo(opponentToBeDealt);
opponentsDealt += 1;
if (opponentsDealt==numberOfOpponents) break;
if (opponentToBeDealt==numberOfOpponents-1) {
opponentToBeDealt = 0;
}
else {
opponentToBeDealt += 1;
}
}
//randomly choose 5 board cards
while (b<5) {
int randomCardTag = rand(&rctx) % 52;
randomCardFlush[b] = randomCardTag/13;
randomCardRank[b] = randomCardTag % 13;
//if this card hasn't been dealt then add to dealt cards
if (Deck[randomCardFlush[b]][randomCardRank[b]]==0) {
Deck[randomCardFlush[b]][randomCardRank[b]] = 1;
b++;
}
}
//evaluate hands (this function also removes random opponent hands when it's done)
calculateMonteCarloEquity();
//remove random board cards from dealt cards
for (int x=0; x<b; x++){
Deck[randomCardFlush[x]][randomCardRank[x]]=0;
}
}
因为我已经写我自己的评价代码,我怀疑是第一次,但是当我做穷举完全相同的代码中,我得到正确的结果(证实PokerStove )。然后我开始考虑是否有对我的对手处理卡牌的方式有任何偏差。这是我的输出:
对手1手 作为AC:1665806次 作为阿:1667998次 作为广告:1666631次 交流啊:1665767次 交流广告:1666595次 阿广告: 1667203次
对手2手 作为AC:833847次 作为阿:833392次 作为广告:8323 96倍 AC阿:833406倍 AC广告:834542倍 阿广告:833703倍 Ks的KC:832585倍 了Ks的Kh:835641倍 了Ks的Kd:832483倍 的Kc的Kh:833013倍 的Kc的Kd:831558倍 Kh Kd:833434次
这对我来说看起来很随意。我也看了一下板卡,似乎也没有任何偏见,除了As-271 812倍,Ac-272 856倍,Ah-271 898倍,Ad以外,基本上所有的卡都处理约1088×××万次 - 272 062次,Ks - 815 113,Kc - 816 871,Kh - 814 955次,Kd - 814 866次,当然还有Js - 0次和Ts - 0次。我也尝试创建一个undealt卡阵列,所以我的随机板卡不会是rand(& rctx)%52,但根据情况rand(& rctx)%46,rand(& rctx)%45 etc(基本上我只选择低价牌)。然而,这并不会改变结果。
我使用ISAAC随机数发生器,虽然我几乎得到与内置rand()函数相同的结果。我试着用randinit(&rctx, time(NULL))
这样的时间播种,但最终结果没有太大差异。是的,我知道时间对于密码学来说是一个糟糕的种子,但对于这样的模拟应该是可以的。
所以我用尽了想法,也许有人可以看到我失踪的东西?
编辑 这里是我的股权计算代码
void calculateMonteCarloEquity() {
opponentsBeaten = 0;
opponentsTied = 0;
opponentsLost = 0;
//remove all opponent cards from dealt cards, because we need 7 dealt cards to evaluate hand
for (int x=0; x<numberOfOpponents; x++) {
Deck[opponentCardFlush[x][0]][opponentCardRank[x][0]] = 0;
Deck[opponentCardFlush[x][1]][opponentCardRank[x][1]] = 0;
}
//at this point we have 5 board cards and 2 player cards left in dealt cards
//so let's evaluate that hand
Evaluate_Hand();
playerHandScore = Hand_Score;
//now remove player hand form dealt cards
Deck[Player_Card_Flush[0]][Player_Card_Rank[0]] = 0;
Deck[Player_Card_Flush[1]][Player_Card_Rank[1]] = 0;
//let's evaluate opponent hands and save their scores
for (int x=0; x<numberOfOpponents; x++) {
//insert opponent x hand to dealt cards
Deck[opponentCardFlush[x][0]][opponentCardRank[x][0]] = 1;
Deck[opponentCardFlush[x][1]][opponentCardRank[x][1]] = 1;
Evaluate_Hand();
opponentHandScore[x] = Hand_Score;
//remove opponent x hand from dealt cards when evaluated
Deck[opponentCardFlush[x][0]][opponentCardRank[x][0]] = 0;
Deck[opponentCardFlush[x][1]][opponentCardRank[x][1]] = 0;
}
//compare opponent hand scores with player hand score
for (int x=0; x<numberOfOpponents; x++) {
if (playerHandScore > opponentHandScore[x]) {
opponentsBeaten += 1;
continue;
}
else if (playerHandScore == opponentHandScore[x]) {
opponentsTied += 1;
continue;
}
else if (playerHandScore < opponentHandScore[x]) {
opponentsLost += 1;
continue;
}
}
//if player beats all opponents he wins the hand
if (opponentsBeaten==numberOfOpponents) {
totalWins += 1;
}
//if player doesn't beat all the opponents, but neither loses to anyone, there must be a tie
if (opponentsLost==0 && opponentsBeaten!=numberOfOpponents) {
totalTies += 1/(opponentsTied+1);
}
//one game has been evaluated
gamesSimulated += 1;
playerEquity = (totalWins+totalTies)/gamesSimulated;
//let's insert player cards back to dealt cards
Deck[Player_Card_Flush[0]][Player_Card_Rank[0]] = 1;
Deck[Player_Card_Flush[1]][Player_Card_Rank[1]] = 1;
if (gamesSimulated>=maxTrials) return;
}
你能显示你的计算19.1%。你有没有考虑到对手会一直有国王和王牌?这意味着在桌子上获得千斤顶和十几张牌的概率是基于46张卡而不是50张卡。 –
你对结果做过统计分析吗?如果正确的值是19.1%,那么得到20.5%的概率是多少? –
我仍然认为理论值(19.1%)可能是错误的。你是如何达到19.1%的? –