帮我为嵌套循环中的对象赋值。
我需要实际调试的代码如下所示:
// Next states
let nextVal = undefined
let nextBoard = undefined
let next_player_value = undefined
shuffle(Board.rowCols).forEach(c => {
shuffle(Board.rowCols[c]).forEach(r => {
if (board[c][r] === undefined) {
board[c][r] = player_state // let's test the current player moving to this location
next_player_value = this.getMinMaxPlayerValue(!player_state)
let minmax = AI.recurseMinMax(next_player_value, board, depth+1)
let value = minmax[0]
if (((player_state===this.getState()) && (nextVal === undefined || value > nextVal)) || // its the AI, and the value increases
((player_state!==this.getState()) && (nextVal === undefined || value < nextVal))) { // its the player, and the value decreases
nextBoard = Object.assign({},board)
nextVal = value
}
board[c][r] = undefined
}
})
})
return [nextVal, nextBoard]
如果您观察调试器,会发生的情况是,它正确地为nextBoard
分配了不同的可能的电路板位置,但是当它在去往return
语句的路上退出外部块时,{{1 }} 变化。它没有成为nextBoard
!相反,它成为当前undefined
而没有任何新的动作(应该存在于Board.state
状态的移动,就像每隔一个空板空间一样)。
undefined
从不 未定义,但它是player_state
的参数(这是此代码的包含函数)。事实上,它始终是recurseMinMax
或true
。我无法轻易替换它 - 我尝试将作业更改为false
和!!player_state
。
这不是嵌套循环或闭包的问题。以下是几个例子:
Object.assign({}, player_state)
为什么这不起作用:
> let a; b = {}; keys=[1]; values =[2];
keys.forEach(key => {
values.forEach(value => {
b[key]=value;
a = Object.assign({},b)
})
})
< undefined
> a
< Object {1: 2}
这就像在我的实际代码中一样。
应该是当前的let nextBoard = undefined
[0,1,2].forEach(i =>{
[0,1,2].forEach(j =>{
if (board[i][j] == null) {
board[i][j] = player;
var value = recurseMinimax(board, !player)[0];
if ((player && (nextVal == null || value > nextVal)) || (!player && (nextVal == null || value < nextVal))) {
nextBoard = Object.assign({},board)
nextVal = value
}
board[i][j] = null;
}
})
})
,但还有一个额外的动作,在Board.state
分配。
现在,有趣的是,当我们使用这样的数组时,我可以非常轻松地使用它:
board[i][j] = player;
这个工作得很好。
问题是,我的实际主板不是嵌套数组,而是嵌套哈希:
[0,1,2].forEach(i =>{
[0,1,2].forEach(j =>{
if (board[i][j] == null) {
board[i][j] = player;
var value = recurseMinimax(board, !player)[0];
if ((player && (nextVal == null || value > nextVal)) || (!player && (nextVal == null || value < nextVal))) {
nextBoard = board.map(function(arr) {
return arr.slice();
});
nextVal = value
}
board[i][j] = null;
}
})
})
答案 0 :(得分:1)
这是因为Object.assign({},board)
采用浅层副本,即board
中的行与您从Object.assign
返回的值相同。
你应该采取深刻的副本。
执行此操作的一种愚蠢方法是使用JSON
:
nextboard = JSON.parse(JSON.stringify(board));
...虽然这仅在board
仅包含JSON支持的基本类型时才有效(所以没有函数,集合,映射......)。
有关其他解决方案,请参阅How to deep clone in JavaScript
例如我自己的this answer:
function deepClone(obj, hash = new WeakMap()) { if (Object(obj) !== obj) return obj; // primitives if (hash.has(obj)) return hash.get(obj); // cyclic reference var result = Array.isArray(obj) ? [] : obj.constructor ? new obj.constructor() : Object.create(null); hash.set(obj, result); if (obj instanceof Map) Array.from(obj, ([key, val]) => result.set(key, deepClone(val, hash)) ); return Object.assign(result, ...Object.keys(obj).map ( key => ({ [key]: deepClone(obj[key], hash) }) )); }
......一旦你有了这个功能,你可以这样做:
nextboard = deepClone(board);
函数中的某些功能可能对您没用(例如支持循环引用和Map
),因此您可以根据需要进行简化。