0

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

    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编写。谢谢

4

3 回答 3

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协议并实现isEqualandhash方法。

有关如何遵守的更多信息NSCopying实施 NSCopying

有关如何实施isEqual和的更多信息hash覆盖 isEqual: 和哈希的最佳实践

完成后,您使用对象本身来检索其概率并更新它,将上述代码转换为类似

// 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");

你可以很容易地想到将这个检查捆绑在一个方法中,并在每次修改概率表时调用它

于 2013-04-07T16:58:38.660 回答
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,您的概率数组就会自动更新。否则,你最终肯定会遇到问题。

于 2013-04-07T17:08:32.310 回答
1

我和你有同样的问题,偶然发现了这个非常有用的链接

链接中的代码是用 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 次。我进行了大约六次测试,每次生成百分比几乎都是正确的。您可能希望稍微自定义上述代码以满足您的需求,但算法的逻辑已经过测试并且可以正常工作。

享受!

于 2014-08-12T07:10:19.060 回答