2013-04-07 116 views
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

最簡單的設計是有一個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"); 

你容易想到​​的方法捆綁此次檢查的並在每次修改概率表時調用它

+0

編程上有意義,我看到的唯一問題是更新,這也需要您更新每個其他對象的概率,使總數仍等於100%,並且這些對象的概率變化是正確加權的。 – user339946 2013-04-07 17:28:11

+0

這是問題的內在原因,除非您提供一些更新其他值的智能默認值,否則「系統」將不知道如何平衡更新。你可能會決定有一些自動行爲(重新分配所有其他對象之間的差異)幷包裝提供這種行爲的'update'調用。 – 2013-04-07 17:31:30

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,你的概率數組就會自動更新。否則,你最終肯定會遇到問題。

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 
} 

要確定,該算法工作,我創建三個對象具有60,30和10一個spawnWeight,並調用此方法1000倍。我進行了大約六次的測試,並且每次出現的百分比幾乎都是現貨。您可能需要對上述代碼進行一些自定義以適應您的需求,但算法的邏輯經過測試並且可行。

享受!