2014-04-12 58 views
2

我最近使用JavaScript編寫的極小極大算法,但是當我執行遞歸,JavaScript的遞歸變量問題

似乎以一種不可思議的方式變量的變化,這裏是代碼:

function moveValue(istate, move, moveFor, nextTurn, depth){ 

    console.log("the original state is: ", istate) 
    var state = stateMove(istate, move, nextTurn); 
    var winner = status.detectWin(state) 
    console.log("now the istate is:", istate) 
    console.log("now the state is: ", state) 

    if (winner == 'tie'){ 
     return 0; 
    } else if (winner != 0){ 
     if (moveFor == nextTurn) return 10 - depth; 
     else return depth - 10; 
    } 

    //if the the current operation is not the same with the original, minimum scenario 
    //if the the current operation is the same with the original, maximum scenario 
    var hope = 999; 
    if (moveFor != nextTurn) hope = -999; 

    var moves = getLegalMoves(state); 

    for (var i=0; i<9; i++){ 
     if (moves.indexOf(i) > -1) { 
      var value = moveValue(state, i, moveFor, -nextTurn, depth+1); 
      if (moveFor == nextTurn && value < hope ||moveFor != nextTurn && value > hope){ 
       hope = value; 
      }    

     } 
    } 

    return hope; 

} 

其中函數在moveValue函數調用

function perfectMove(){ 
    var state = status.getState(); 
    var winner = status.detectWin(state); 

    if (winner == 0){ 
     var moves = getLegalMoves(state); 

     //Because the AI is unbeatable, so this is the minimum scenario 
     var hope = -999; 
     var goodMoves = [] 
     //var is = [] 

     //not blank or just one scenario 
     if (goodMoves.length == 0){ 
      for (var i=0; i<9; i++){ 
       //for these legal move 
       if (moves.indexOf(i)> -1) { 
        var value = moveValue(state, i, turn, turn, 1); 
        if (value > hope){ 
         hope = value; 
         goodMoves = []; 
        } 
        //get all the possible best move 
        if (hope == value){ 
         goodMoves.push(i); 
        } 
       } 
      } 
     } 
     moveRandom(goodMoves); 
    } 
} 

,我CONSOLE.LOG狀態和即將狀態置,我發現,狀態和即將狀態置在這也是讓我無法同時變化了解有關程序,並在遞歸

回報的狀態保持不變(不回到以前的調用堆棧值)

getState是,我在文件中創建單元格並使用require.js注入每次我想要使用它。

function getState(){ 
    var state = []; 
    for (var i=0; i<9; i++){ 
     state.push(cells[i].value) 
    } 

    return state; 
} 

stateMove功能在這裏,並且firstPlayer,secondPlayer是相同的方式與細胞

function stateMove(state, move, nextTurn){ 
    var value = firstPlayer; 
    if (nextTurn == -1) value = secondPlayer; 
    state[move] = value 
    return state 
} 
+1

我懷疑你的'stateMove'功能改變'istate'陣列_in place_而不是複製。如果您爲該功能添加代碼,則會使問題更易於診斷。 –

+0

嗨,@musically_ut,我添加它,謝謝你的回答 –

回答

1

stateMove功能突變傳遞給它的陣列。改變它,使得它創建數組的副本將解決這個問題:

function stateMove(state, move, nextTurn){ 
    var nextState = state.slice(0); 
    var value = firstPlayer; 
    if (nextTurn == -1) value = secondPlayer; 
    nextState[move] = value; 
    return nextState; 
} 
+0

哇,你能解釋一下嗎?它怎麼能改變通過參數傳遞的狀態?它關閉了嗎?但它非常不典型@musically_ut –

+0

@ user3526776除了在基元的情況下,Javascript成爲通過引用語言傳遞的關鍵。所以如果你改變了對象的所有_property_(記住索引值也是屬性)(數組也是一個對象+ niceties),那麼原始值將被改變。這裏的解釋更加完整:http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language –

+0

非常感謝!我一直呆在這裏一整天!再次感謝 –