2048中放置新数字位置算法分析
时间:2014-05-20T13:56
源码来源:钱同学
while (1)
{
RandRow = rand() % 4;
RandCol = rand() % 4;
if (table[RandRow][RandCol] == 0)
{
table[RandRow][RandCol] = num;
break;
}
}
//0代表这个格子没有数字
前提条件1: 用 rand() % 4 得到的0,1,2,3四个数出现概率各为4分之1;
前提条件2: 放置前的局面里已有p个位置有数字,q个位置为空位,p+q = 16
1. 如果一次循环就完成新数字的放置,即 q * 1.0 / 16 概率情况,
q个位置每个位置被选中的概率都为 1.0 / 16;
2. 如果n(n>=2)次循环才完成新数字的放置,那么即 pow((p / 16.0), n - 1) * q / 16 概率,
q个位置每个位置被选中的概率都为 1.0 / 16;
该算法的循环次数的数学期望为:
E(times) = 1 * q / 16.0 + 2 * p / 16.0 * q / 16 + 3 * pow(p/16.0, 2) * q / 16 + ... + n * pow(p/16.0, n - 1) * q / 16, n趋向于无穷大
记 q / 16.0 为 Q, p / 16.0 为 P, P = 1 - Q
则E(times) = 1 * Q + 2 * P * Q + 3 * P^2 * Q + ... + n * P ^ (n-1) * Q, n趋向于无穷大
经过一番复杂的运算(数列求和、求极限),得E(times) = 1 / Q ,即 E(times) = q;
(为什么我的直觉告诉我,空位越少,期望越大呢?因为抽不中的概率大了呀,需要抽更多次。)
综上所述,不管运气有多烂,循环了多少次才得出放置位置,摆放位置终究是随机的。
更好的算法
将空位分别标上序号0,1,2,... q - 1;
然后生成随机数0 到 q - 1;
根据生成的随机数反过来找到空位,搞定!
例如定义 struct Location { int col, int row};
定义Location数组: struct Location EmptyList[16]; int ListCount = 0;
顺序扫描一遍table,并记下空位位置于EmptyList中。
生成随机数index = 0 到 ListCount - 1;
取出 loc = emptyList[index];
得到 loc.col 和 loc.row.