Objective c 概率表的设计

Objective c 概率表的设计,objective-c,probability,Objective C,Probability,我正在制作一个游戏原型,用户点击一个按钮,一个项目就会随机出现 Object A = 10% chance of discovery Object B = 15% chance of discovery Object C = 12% chance of discovery etc... totalling 100% 在游戏过程中,用户可能会增加找到某些对象的几率,例如将对象A的概率从10%增加到15% 我想知道是否有人能建议一个有效的设计或函数来运行概率并返回一个对象

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

    Object A = 10% chance of discovery
    Object B = 15% chance of discovery
    Object C = 12% chance of discovery etc... totalling 100%
在游戏过程中,用户可能会增加找到某些对象的几率,例如将
对象A的概率从10%增加到15%

我想知道是否有人能建议一个有效的设计或函数来运行概率并返回一个对象

起初,我考虑随机生成一个从1到100的数字,然后使用一系列的
if/else if
语句,但这似乎很乏味,而且对于更新项目概率来说也不是很灵活。此外,我是否应该将概率存储在和NSDictionary中


如有任何建议,我们将不胜感激。我是用Objective-C写的。谢谢

最简单的设计就是以这种方式拥有一个
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
协议,并实现
isEqual
hash
方法

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

有关如何实现
isEqual
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");

您可以很容易地想到将此检查捆绑到一个方法中,并在每次修改概率表时调用它。最简单的设计是以这种方式拥有一个
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
协议,并实现
isEqual
hash
方法

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

有关如何实现
isEqual
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");

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

对象是否唯一?如果是,请创建一个容纳所有对象的包

NSArray *legendarySwords=....
只需从该数组中删除任意元素

如果对象不是唯一的——你有一台自动售货机,可以根据玩家的承受能力分发尽可能多的对象——那么就使用你的阵列

@[ 0.10, 0.15, 0.12 ...]
并构造了累积概率

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

现在,生成一个随机数[0,1];数组中的第一个元素对象是唯一的吗?如果是,请创建一个容纳所有对象的包

NSArray *legendarySwords=....
只需从该数组中删除任意元素

如果对象不是唯一的——你有一台自动售货机,可以根据玩家的承受能力分发尽可能多的对象——那么就使用你的阵列

@[ 0.10, 0.15, 0.12 ...]
并构造了累积概率

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

现在,生成一个随机数[0,1];数组中的第一个元素我遇到了与您相同的问题,并且偶然发现了这个非常有用的问题

链接中的代码是用ActionScript3编写的,下面是我的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
}
-(MyObject*)getWeightedRandomObject
{
int weightscenter=0;//添加的当前权重之和
//计算所有障碍物的总重量
用于(objectsArray中的MyObject*对象)
{
weightsCounter+=对象的权重;
}
int random=arc4random\u uniform(weightscenter)+1;//随机int从1到总权重(包括在内)。
权重中心=0;
//拾取加权对象
用于(objectsArray中的MyObject*对象)
{
weightsCounter+=对象的权重;
if(随机<权重中心)
{
返回对象;
}
}
return[objectsArray lastObject];//此时只剩下最后一个对象
}
为了确保该算法有效,我创建了三个对象,其权重分别为60、30和10,并调用了该方法1000次。我进行了六次测试,每次的产卵率几乎都是准确的。您可能想定制上面的代码以满足您的需要,但是算法的逻辑已经过测试并可以工作


享受吧

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

链接中的代码是用ActionScript3编写的,下面是我的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
}
-(MyObject*)getWeightedRandomObject
{
int weightscenter=0;//添加的当前权重之和
//计算所有障碍物的总重量
用于(objectsArray中的MyObject*对象)
{
weightsCounter+=对象的权重;
}
int random=arc4random\u uniform(weightscenter)+1;//随机int从1到总权重(包括在内)。
权重中心=0;
//拾取加权对象
用于(objectsArray中的MyObject*对象)
{
WeightsCenter+=object.s