0.说明
学习德州扑克时,不可避免需要计算赔率来指导自己决策。
实战中计算赔率需要考虑很多因素,包括且不限于:价值赔率、对手打法、自己形象等等。
但其中价值赔率是最稳定且关键的赔率。
比如手握 ♠️A♦️A,桌面 ♦️K♦️Q♦️J,这种情况下期望胜率是多少?如果是 1v1 且笃定对手手牌为 ♦️T♥️T 的情况下胜率又是多少?
甚至有的时候我们还想知道我们的牌会以多大的概率输给高牌、对子或者葫芦?
总之能计算这些概率是非常重要的。德扑高手或者数学高手可能能较快地算出大致概率,网上也有一些工具可以帮助计算,不过自己实现定制化灵活度更高一些,可以根据需要随意改。
理论上是可以直接从牌局用数学的排列组合方法去计算概率的。
但这里个人采取更简单粗暴的蒙特卡洛方法:直接随机模拟很多次发牌,统计结果。
如果要求高精度,大可将模拟次数设高一些。
代码支持多线程,多核 CPU 可以并行计算更快地得到结果。
1.源代码
代码基于 Java 实现
Github 链接:https://github.com/Raytto/HoldemCaculator
2.工程结构
-- scr
-- model 一些基本类
-- Desk.java 牌桌类
-- Player.java 玩家类
-- PokerCard.java 一张牌
-- processor 计算器
-- BasicProcessor.java 各种牌型判断
-- MCprocessor.java 蒙特卡洛模拟
-- test 根据实际需要使用计算器进行情景模拟的一些例子
-- MCprocessorTest1.java 一场五人局,知道自己和另一个对手的手牌下的胜负情况
-- OnlyHoldCardsInfoSituationToFile.java 将结果输出至文件的实例
3.使用说明
类似 test 中的各种使用方式,如 MCprocessorTest1.java
package test;
import model.Desk;
import model.Player;
import model.PokerCard;
import processor.MCprocessor;
public class MCprocessorTest1 {
public static void main(String[] args) { // TODO Auto-generated method stub Player player1=new Player(); player1.setSerialNumber(0); Player player2=new Player(); player2.setSerialNumber(1); Player player3=new Player(); player2.setSerialNumber(2); Player player4=new Player(); player2.setSerialNumber(3); Player player5=new Player(); player2.setSerialNumber(4); Player player6=new Player(); player2.setSerialNumber(5); player1.getHoldCards().add(new PokerCard(14, PokerCard.Hearts)); player1.getHoldCards().add(new PokerCard(10, PokerCard.Dimonds)); player2.getHoldCards().add(new PokerCard(3, PokerCard.Dimonds)); player2.getHoldCards().add(new PokerCard(5, PokerCard.Dimonds));
// player3.getHoldCards().add(new PokerCard(3, PokerCard.Spades));
// player3.getHoldCards().add(new PokerCard(3, PokerCard.Hearts));
Desk desk=new Desk();
desk.getPlayers().add(player1);
desk.getPlayers().add(player2);
// desk.getPlayers().add(player3);
// desk.getPlayers().add(player4);
// desk.getPlayers().add(player5);
// desk.getPlayers().add(player6);
// desk.getCommunityCards().add(new PokerCard(7,PokerCard.Dimonds));
// desk.getCommunityCards().add(new PokerCard(9,PokerCard.Dimonds));
// desk.getCommunityCards().add(new PokerCard(11,PokerCard.Dimonds));
// desk.getCommunityCards().add(new PokerCard(12,PokerCard.Dimonds));
// desk.getCommunityCards().add(new PokerCard(13,PokerCard.Dimonds));
MCprocessor mc=new MCprocessor();
System.out.println("------------start-----------");
long startTime = System.nanoTime();
try {
int time=10000000;
int[][][]result=mc.timesOfWinOfEachPlayers(time, desk);
System.out.println("------------win info-----------");
for(int p=0;p<desk.getPlayers().size();p++){
for(int i=0;i<=desk.getPlayers().size();i++){
System.out.print(result[0][p][i]+"("+(double)result[0][p][i]/time+") ");
}
System.out.println();
}
System.out.println("------------win kind-----------");
for(int p=0;p<desk.getPlayers().size();p++){
for(int i=0;i<=8;i++){
System.out.print(result[1][p][i]+"("+(double)result[1][p][i]/time+") ");
}
System.out.println();
}
System.out.println("-----------lose kind-----------");
for(int p=0;p<desk.getPlayers().size();p++){
for(int i=0;i<=8;i++){
System.out.print(result[2][p][i]+"("+(double)result[2][p][i]/time+") ");
}
System.out.println();
}
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
}
long consumingTime = System.nanoTime() - startTime;
System.out.println(consumingTime/1000000+" ms");
}
}
运行即可打印出胜负情况,且可以知道胜利的情况下分别对手各牌型比例,以及输的情况下对手的各个牌型的比例