2012-12-21 101 views
2

我正在研究簡單的進化AI。我需要動態生成一個匿名函數。對於它,我具有條件和動作的列表:動態創建匿名函數?

var conditions = [ 
    function() { return enemyNear(), }, 
    function() { return mySpeed() > 5; }, 
    function() { return 1 === 1; }]; 
    var actions = [ 
     function() { return alert('walk'); }, 
     function() { return alert('jump'); } 
     function() { return alert('attack'); } ] 

該代碼選擇每一個,以產生一個新的功能:

condition = conditions [Math.floor(Math.random()*conditions .length)]; 
actions = conditions [Math.floor(Math.random()*actions .length)]; 

只要所選擇的條件是enemyNear()和所選擇的動作是walk() ,我怎樣才能生成簡單的匿名函數?

behavior = function() { 
    if(enemyNear()) { 
     walk(); 
    } 
} 

我可以根據需要更改數組的保存方式。如何才能做到這一點?

所有字符behaviors被稱爲像這樣的循環中:

for(i=0,i<chars.length,i++) { 
chars[i].behavior.call(); 
} 
+0

問題是,當您將它們放入數組中時,您已經調用了函數。 'walk'是對函數的引用,而'walk()'調用函數並使用返回值。 – kapa

+0

我想像過這些函數沒有正確保存在數組中,我可以根據需要更改它們的保存方式。 – lisovaccaro

回答

3

首先,數組裏面,你會需要有一個參考的條件和操作功能。現在,你打電話給他們,所以他們基本上是相同的一個無用的陣列,如:

conditions = [true, false, true]; 
actions = [undefined, undefined, undefined]; 

我會把它糾正到這樣的事情:

var conditions = [enemyNear, 
    function() { return mySpeed() > 5 }, 
    function(){ return true; }]; 
var actions = [walk, attack, jump]; 

然後你就可以創建一個功能其產生的行爲:

function generateBehavior(){ 
    var condition = conditions[Math.floor(Math.random() * conditions.length)]; 
    var action = actions[Math.floor(Math.random() * actions.length)]; 
    return function() { 
    if(condition()) { 
     action(); 
    } 
    } 
} 

你可以看到它在行動上這個JSFiddle demo

+0

這個完美的作品。這確實在原始問題之外,但是有沒有辦法在以後修改一個函數呢? EG:添加第二個條件?只是一個雖然,但它是可能的,把它變成一個字符串(做任何我想用它),並將其變成一個函數,所以我避免eval?這真的是最好的能夠做到這一點,因爲使用字符串會給我很多versovaility – lisovaccaro

+0

@ Liso22而不是'if(condition())',你可以從條件數組中選擇一個索引,並執行' if(conditions [i])'然後將'conditions [i]'改爲另一個函數 –

3

從此改變你的陣列:

conditions = [enemyNear(), mySpeed()>5, 1=1]; 

要這樣:

conditions = [ 
    function() { return enemyNear() }, // or just enemyNear 
    function() { return mySpeed() > 5 }, 
    function() { return 1 == 1 } // 1 = 1? 
]; 

以您目前的代碼,你的函數被調用,並且conditions成爲一個outp的數組這些功能。

-6

簡單。使用eval()

var behavior; 
eval("behavior = function() { if (enemyNear()) walk(); }"); 
behavior(); 
+0

eval?真的嗎? – Joseph

+1

不鼓勵使用'eval'。更好的方法是存儲函數,然後調用每個函數 –

+0

這個問題聽起來像是需要自編程行爲。爲此,需要eval()。 – Tyron

0

您需要存儲您的功能array,不給他們打電話,否則你存儲結果的數組中的功能

function enemyNear() {} 
function walk() {} 

conditions = [enemyNear] 
actions = [walk] 

behaviour = function() { 
    if(conditions[randomNumber]()) { 
    actions[randomNumber](); 
    } 
} 
4

最簡單的方法是隻把數組裏面的功能:

var conditions = [ 
    enemyNear, 
    function() { return mySpeed() > 5; }, 
    function() { return 1 === 1; 
}]; 
var actions = [walk, attack, jump]; 

則你可以定義behave,就像這樣:

var behave = function(condition, action) { 
    if(condition()) { 
     action(); 
    } 
} 

而且這樣使用它,例如:

behave(conditions[2], actions[1]); 

這裏,21可能是隨機生成的數字是這樣的:

var getRandomInt = function (min, max) { 
    return Math.floor(Math.random() * (max - min + 1)) + min; 
} 

var actRandomly = function (conditions, actions) { 
    behave(
     conditions[getRandomInt(0, conditions.length -1)], 
     actions[getRandomInt(0, actions.length -1)] 
    ); 
}; 

這樣稱呼它:

actRandomly(conditions, actions); 

當然,這只是提出這個想法,而不是井然有序。

爲了好玩,我創建了一個Basic jsFiddle Demo Version


注:當你定義一個變量始終使用var。不要污染全球範圍。

+0

這是一個很好的解決方案。我不知道它是否適用於我的案件。首先,當我調用函數時,我無法傳遞任何值。我想這可能是固定的。另外我需要很多不同的處理字符串的方法:使用字符串我可以簡單地創建一個解析它的函數,讓我修改條件,添加兩個條件,更改操作。也許有一種方法可以對它進行字符串化並將其改回或解析該函數​​並對其進行修改。 (我不知道是否有必要這樣做,我只是頭腦風暴)如果我不能說更多的話,我很抱歉,這個小盒子沒有幫助。 – lisovaccaro

1
condition = [ 
    enemyNear, 
    function() { return mySpeed() > 5; }, 
    function() { return 1 == 1; } 
];