我目前正在开发一个java应用程序,我需要计算滚动各种骰子的每个总和的概率。我支持的骰子类型是d4(4面骰子),d6(6面骰子),d8(8面骰子),d10,d12和d20。用户将能够输入他们想要在计算中使用的每种骰子的数量。例如,用户可以输入6 d6和4 d4。
有了这个给定的信息(每种类型的骰子数),我希望计算每个可能的总和可以滚动的概率。然后,我将使用此信息创建一个图表,显示所选骰子组合的概率分布。
此应用程序是用Java编写的。
我目前在的地方是,我有一个函数可以计算仅使用一个骰子大小的特定总和的概率
/*
Recursively calculates the probability of rolling a particular number
when rolling multiple dice of one type
@param dice Number of dice
@param seekedValue Value whose probability is being calculated
@param sides Number of sides on the type of die
*/
private double diceProb(int dice, int seekedValue, int sides){
if (dice == 0){
if (seekedValue == 0){
return 1.0;
} else {
return 0.0;
}
} else {
double sum = 0;
for (int i = seekedValue - sides; i < seekedValue; i++){
sum += diceProb(dice -1, i, sides) / sides;
}
return sum;
}
}
然后我使用此代码查找所有可能的概率
/*
Variable Explanations:
diceEntries: This array list contains the number of each dice supplied by the user.
It is ordered by number of sides, with d4 at the beginning and d20 at the end
diceValues: This array contains the sides of the dice types
probArray: this array list will contain the probabilities of each sum possible
min: the minimum sum possible
max: the maximum sum possible
*/
ArrayList<Integer> diceEntries
ArrayList<Float> probArray = new ArrayList<>();
int[] diceValues = {4,6,8,10,12,20};
float prob = 0;
for (int i = min; i <= max; i++){
for (int j = 0; j <= 5; j++) {
prob = (float) diceProb(diceEntries.get(j), i, diceValues[j]);
if (prob != 0) {
probArray.add(prob);
}
}
}
我目前的代码只能处理一种尺寸的骰子,即只有d6s或d4s,而不是它们的混合。
如果社区可以提供一些指导,我们将不胜感激。我也愿意接受这些方法。例如,我已经读过生成函数可能是一种更好的方法,但是我的组合数据有点弱,如果有人确实有编码方法,那么很高兴看到它。
非常感谢大家
答案 0 :(得分:3)
蛮力方法的另一个条目,使用整数列表(骰子边)来处理多个骰子类型。优点是,如果你想要很多概率,你可以运行一次然后只查询各种概率。缺点是,作为一种蛮力方法,它只能获得单一概率的效率非常低。
public int[] probs;
public void genRolls(int sum, List<Integer> sides)
{
if (sides.size() == 0)
{
probs[sum]++;
return;
}
int top = sides.get(0);
for (int x = 1; x <= top; x++)
genRolls(sum+x, sides.subList(1, sides.size()));
}
public void diceprob(int target, List<Integer> sides)
{
int maxval = 0;
double possibilities = 1;
for (Integer i : sides)
{
maxval+= i;
possibilities *= i;
}
probs = new int[maxval+1];
genRolls(0, sides);
System.out.println("Probability is " + (probs[target]/possibilities));
}
答案 1 :(得分:0)
您可以简单地模拟所有组合。下面的代码对nD6
执行此操作,但该示例应该可以扩展为多个骰子类型。
public class Main {
static final int FACES = 6;
int[] buckets;
int[] currentCombination;
int totalCombinations;
public Main(int numberOfDices) {
this.buckets = new int[FACES * numberOfDices];
this.currentCombination = new int[numberOfDices];
this.totalCombinations = 0;
}
public void calculate() {
calculate(this.currentCombination.length);
for (int i = 0; i < this.buckets.length; ++i) {
System.out.println((i + 1) + ":\t" + this.buckets[i] + " / "
+ this.totalCombinations);
}
}
public void calculate(int dicesLeft) {
if (0 == dicesLeft) {
int sum = 0;
for (int die : this.currentCombination) {
sum += die;
}
++this.buckets[sum - 1];
++this.totalCombinations;
} else {
--dicesLeft;
for (int die = 1; die <= FACES; ++die) {
currentCombination[dicesLeft] = die;
calculate(dicesLeft);
}
}
}
public static void main(String... args) {
int n = Integer.parseInt(args[0]);
Main m = new Main(N);
m.calculate();
}
}
答案 2 :(得分:0)
自变量之和的概率是每个变量概率的卷积。对于离散变量,卷积是一个简单的求和,您可以在Java中轻松实现。我的建议是组织这样的计算:
get numbers of dice and numbers of sides
for each die
construct array with length=number of sides and each element=1/(number of sides)
let convolution result=first array
for second through rest of arrays
let convolution result = convolution(result, next array)
output result
几个函数的卷积可以一次计算两个;什么顺序并不重要。
两个数组a
和b
的卷积只是:
for i=0 through length(a) + length(b) - 2 inclusive,
conv[i] = sum(a[j]*b[i - j], j, max(0, i - length(b) + 1), min(length(a) -1, i))
您可以使用Octave非常方便地查看结果。 conv
是Octave中的卷积函数。