设计概率表

时间:2013-04-07 16:54:29

标签: objective-c probability

我正在制作游戏原型,用户点按一个按钮,随机出现一个项目。

    Object A = 10% chance of discovery
    Object B = 15% chance of discovery
    Object C = 12% chance of discovery etc... totalling 100%

在游戏进程中,用户可能会增加查找某些对象的几率,例如增加Object A's probability from 10% to 15%

我想知道是否有人可以建议一个有效的设计或功能来运行概率和返回一个对象。

起初我认为只是随机生成1到100之间的数字,然后使用一系列if/else if语句,但这对于更新项目概率来说似乎很乏味且不太可塑。另外,我应该将概率存储在和NSDictionary中吗?

任何建议表示赞赏。我在写Objective-C。感谢

3 个答案:

答案 0 :(得分:4)

最简单的设计是以这种方式拥有NSMutableDictionary(可变,因为你需要更新它)

NSMutableDictionary * probabilityTable = @{
    @"objectA" : @0.10, // the @ converts the number to a `NSNumber` (NSDictionary accepts only objects)
    @"objectB" : @0.15,
    @"objectC" : @0.12
};

等等。

然后为了检索概率

probabilityTable[@"objectA"];

并进行更新

probabilityTable[@"objectA"] = @0.16;

修改

为了获得额外的乐趣,您可以将对象本身用作字典键。为了做到这一点,请将这些对象设为类MyObject的子类(我假设您将为不同的对象类别设置不同的类)。此类必须符合NSCopying协议并实施isEqualhash方法。

有关如何符合NSCopying的更多信息:Implementing NSCopying

有关如何实施isEqualhash的更多信息:Best practices for overriding isEqual: and hash

执行此操作后,您可以使用对象本身检索其概率并更新它,将上述代码转换为

// initializing 
NSMutableDictionary * probabilityTable = @{
    objectA : @0.10,
    objectB : @0.15,
    objectC : @0.12
};

// retrieving
probabilityTable[objectA];

// updating
probabilityTable[objectA] = @0.16;

编辑2

如果你想获得幻想,你也可以写一个断言来检查概率总和是否为1.检查看起来像

float sum = 0;
for (NSNumber * n in probabilityTable.allValues) {
    sum += n.floatValue;
}
NSAssert(sum == 1.0, @"Sum of probabilities must be 1.0");

您可以轻松地考虑将此检查捆绑在一个方法中,并在每次修改概率表时调用它

答案 1 :(得分:1)

对象是否独一无二?如果是这样,请创建一个包含所有对象的包

NSArray *legendarySwords=....

并从该数组中删除任意元素。

如果对象不是唯一的 - 你有一台自动售货机可以分配每个对象的数量,就像玩家可以承受的那样 - 拿走你的阵列

@[ 0.10, 0.15, 0.12 ...]

并构建累积概率

@[ 0.10, 0.25, 0.37 .... 1]

现在,生成一个随机数[0,1];数组中的第一个元素< =随机数给你选择。

但这对维护来说会很痛苦。一个更好的解决方案将填充具有相对概率的一堆对象:

NSThing *canteen=[[NSThing alloc] initWithCost: 10 abundance: kCommon];

NSThing *magicArrow=[[NSThing alloc] initWithCost: 100 abundance: kRare];

NSInventory *inventory=[NSInventory inventoryFor: @[canteen, magicArrow, ...];

然后从清单构建概率数组。需要制作箭头kVeryRare才能发挥平衡作用?您只需要更改magicArrow,您的概率数组将自动更新。否则,你最终肯定会遇到问题。

答案 2 :(得分:1)

我遇到了和你一样的问题,偶然发现了这个非常有帮助的link

链接中的代码是用ActionScript 3编写的,所以这是我的Objective-c转换代码。我

- (MyObject *)getWeightedRandomObject
{
    int weightsCounter =  0; // sum of the current weights added

    // get the total weight of all the obstacles
    for (MyObject* object in objectsArray)
    {
        weightsCounter += object.spawnWeight;
    }

    int random = arc4random_uniform(weightsCounter) + 1; // random int from 1 to total weight inclusive.
    weightsCounter = 0;

    // pick the weighted object
    for (MyObject* object in objectsArray)
    {
        weightsCounter += object.spawnWeight;

        if (random < weightsCounter)
        {
            return object;
        }
    }

    return [objectsArray lastObject]; // only the last object will be remaining at this point
}

为确保此算法有效,我创建了三个对象,其spawnWeight为60,30和10,并将此方法称为1000次。我进行了大约六次测试,每次产卵百分比几乎都是现场测试。您可能希望稍微自定义上述代码以满足您的需求,但算法的逻辑已经过测试并且有效。

享受!