老虎机有5个卷轴,每个卷轴显示3个符号(没有空格或"空"符号)。
付款可以通过多种方式进行。一些例子......
还需要检查多条支付线以获得付款。
每次旋转计算奖金的最有效方法是什么?或者,是否有比蛮力更有效的方式将每个支付方案应用于每条支付线?
答案 0 :(得分:9)
支付线以外的每一笔支出都显得微不足道。对于三个幸运的7,只需迭代可见的方块并计算7s。检查钻石也是如此。如果我们让 h 为行数且 w 为列数,则此操作为O( h w *),其中实际尺寸的老虎机非常低。
但是,支付线更有趣。从理论上讲,支付线的数量( m 从此处开始)远远大于* h ** w *;在抛出跳过 m = h ^ w 的非法支付线之前,它远远大于* h ** w 。更重要的是,它们似乎有很多相似之处。例如,示例中的第2行和第6行都需要匹配左上角和上左中角。如果这两者不匹配,那么你就无法在第2行或第6行获胜。
为了表示支付线,我将在[1, h ]范围内使用长度为 w 的整数数组,这样payline [i] =解决方案中第i行的列(索引为1)中的索引。例如,支付线1为[1,1,1,1,1],支付线17为[3,3,2,1,2]。
为此,suffix tree似乎是一个适用的数据结构,可以极大地改善检查给定董事会状态的所有支付线的运行时间。请考虑以下算法来构建封装所有支付线的后缀树。
Initialize:
Create a root node at column 0 (off-screen, non-column part of all solutions)
root node.length = 0
root node.terminal = false
Add all paylines (in the form of length w arrays of integers ranging from 1 to h) to the root nodes' "toDistribute set"
Create a toWork queue, add the root node to it
Iterate: while toWork not empty:
let node n = toWork.pop()
if n.length < w
create children of n with length n.length + 1 and terminal = (n.length + 1 == w).
for payline p in n.toDistribute
remove p from n.toDistribute
if(p.length > 1)
add p.subArray(1, end) to child of n as applicable.
add children of n to toWork
在第1-11行的示例中运行此构造算法会得到如下所示的树:
这棵树的计算相当密集;它涉及创建sum i = 1 to w of h ^ i
个节点。树的大小仅取决于板的大小(高度和宽度),而不取决于支付线的数量,这是这种方法的主要优点。另一个优点是它都是预处理;你可以在玩家坐下来拉杆之前很久就建造这棵树。
构建树后,您可以为每个节点提供每个匹配条件的字段(相同的符号,相同的颜色等)。然后,在评估板状态时,您可以对树进行dfs,并在每个新节点上询问(对于每个critera)它是否与其父节点匹配。如果是,请将该标准标记为true并继续。否则,将其标记为false并且不要搜索孩子的标准。例如,如果您专门查找子阵列[1,1,...]上的相同令牌,并找到第1列第1行和第2列第1行并且#39 ;匹配,然后包括[1,1,...](2,6,16,20)的任何支付线都不能赢,而且你不必dfs那部分dfs树。
很难对这种dfs方法的效率进行彻底的算法分析,而不是单独检查每条支付线,因为这样的分析需要知道左侧重叠(平均)有多少支付线。它当然不会更糟,至少对你的例子来说是一个更好的交易。此外,您添加到电路板的支付线越多,重叠越大,使用此方法检查所有支付线的时间就越长。
答案 1 :(得分:1)
为了计算RTP,您应该拥有完整的老虎机信息。最重要的部分是卷轴条。蒙特卡洛通常是为了获得所需的统计数据。例如:https://raw.githubusercontent.com/VelbazhdSoftwareLLC/BugABoomSimulator/master/Main.cs
支付信息:
private static int[][] paytable = {
new int[]{0,0,0,0,0,0,0,0,0,0,0,0,0},
new int[]{0,0,0,0,0,0,0,0,0,0,0,0,0},
new int[]{0,0,0,0,0,0,0,0,2,2,2,10,2},
new int[]{5,5,5,10,10,10,15,15,25,25,50,250,5},
new int[]{25,25,25,50,50,50,75,75,125,125,250,2500,0},
new int[]{125,125,125,250,250,250,500,500,750,750,1250,10000,0},
};
投注线:
private static int[][] lines = {
new int[]{1,1,1,1,1},
new int[]{0,0,0,0,0},
new int[]{2,2,2,2,2},
new int[]{0,1,2,1,0},
new int[]{2,1,0,1,2},
new int[]{0,0,1,2,2},
new int[]{2,2,1,0,0},
new int[]{1,0,1,2,1},
new int[]{1,2,1,0,1},
new int[]{1,0,0,1,0},
new int[]{1,2,2,1,2},
new int[]{0,1,0,0,1},
new int[]{2,1,2,2,1},
new int[]{0,2,0,2,0},
new int[]{2,0,2,0,2},
new int[]{1,0,2,0,1},
new int[]{1,2,0,2,1},
new int[]{0,1,1,1,0},
new int[]{2,1,1,1,2},
new int[]{0,2,2,2,0},
};
卷轴条:
private static int[][] baseReels = {
new int[]{0,4,11,1,3,2,5,9,0,4,2,7,8,0,5,2,6,10,0,5,1,3,9,4,2,7,8,0,5,2,6,9,0,5,2,4,10,0,5,1,7,9,2,5},
new int[]{4,1,11,2,7,0,9,5,1,3,8,4,2,6,12,4,0,3,1,8,4,2,6,0,10,4,1,3,2,12,4,0,7,1,8,2,4,0,9,1,6,2,8,0},
new int[]{1,7,11,5,1,7,8,6,0,3,12,4,1,6,9,5,2,7,10,1,3,2,8,1,3,0,9,5,1,3,10,6,0,3,8,7,1,6,12,3,2,5,9,3},
new int[]{5,2,11,3,0,6,1,5,12,2,4,0,10,3,1,7,3,2,11,5,4,6,0,5,12,1,3,7,2,4,8,0,3,6,1,4,12,2,5,7,0,4,9,1},
new int[]{7,0,11,4,6,1,9,5,10,2,7,3,8,0,4,9,1,6,5,10,2,8,3},
};
private static int[][] freeReels = {
new int[]{2,4,11,0,3,7,1,4,8,2,5,6,0,5,9,1,3,7,2,4,10,0,3,1,8,4,2,5,6,0,4,1,10,5,2,3,7,0,5,9,1,3,6},
new int[]{4,2,11,0,5,2,12,1,7,0,9,2,3,0,12,2,4,0,5,8,2,6,0,12,2,7,1,3,10,6,0},
new int[]{1,4,11,2,7,8,1,5,12,0,3,9,1,7,8,1,5,12,2,6,10,1,4,9,3,1,8,0,12,6,9},
new int[]{6,4,11,2,7,3,9,1,6,5,12,0,4,10,2,3,8,1,7,5,12,0},
new int[]{3,4,11,0,6,5,3,8,1,7,4,9,2,5,10,0,3,8,1,4,10,2,5,9},
};
旋转函数,应该多次调用以计算RTP:
private static void spin(int[][] reels) {
for (int i = 0, r, u, d; i < view.Length && i < reels.Length; i++) {
if (bruteForce == true) {
u = reelsStops [i];
r = u + 1;
d = u + 2;
} else {
u = prng.Next (reels [i].Length);
r = u + 1;
d = u + 2;
}
r = r % reels[i].Length;
d = d % reels[i].Length;
view[i][0] = reels[i][u];
view[i][1] = reels[i][r];
view[i][2] = reels[i][d];
}
}
每次旋转后,应计算所有胜利。