我将变量G.playerStatsDifference
定义为对象数组:
playerStatsDifference: [{
carpenter: 0,
wood: 0,
gunman: 0,
gunpowder: 0,
merchant: 0,
gold: 0,
fleet: 0,
flagship: 0,
}, {
carpenter: 0,
wood: 0,
gunman: 0,
gunpowder: 0,
merchant: 0,
gold: 0,
fleet: 0,
flagship: 0,
}]
该变量的意义在于计算频繁变化的G.playerStats
之间的差值。
我计算差值的函数是:
const oldPlayerStats = JSON.parse(JSON.stringify(G.playerStats));
statsDifference(G, oldPlayerStats);
for (let p = 0; p < 2; p++) {
for (let s = 0; s < 8; s++) {
Object.values(G.playerStatsDifference[p])[s] = Object.values(G.playerStats[p])[s] - Object.values(oldPlayerStats[p])[s];
}
}
期望的输出是playerStatsDifference
当运行一些测试时,我做了一些控制台日志记录,它给了我正确的计算,但是G.playerStatsDiffence
不会更新。
下面是一些测试,计算是正确的:
console.log("Current wood is " + Object.values(G.playerStats[0])[1]); //Current wood is 5
console.log("Old wood is " + Object.values(oldPlayerStats[0])[1]); //Old wood is 10
console.log(Object.values(G.playerStats[0])[1] - Object.values(oldPlayerStats[0])[1]); //-5
我想也许我在循环中做错了什么,所以后来我尝试了以下操作:
Object.values(G.playerStatsDifference[0])[1] = Object.values(G.playerStats[0])[1] - Object.values(oldPlayerStats[0])[1];
然而,这也不起作用。话虽如此,下面的操作是可行的:
G.playerStatsDifference[0].wood = Object.values(G.playerStats[0])[1] - Object.values(oldPlayerStats[0])[1];
所以看起来我对G.playerStatsDifference
上的Object.values
有一些问题。有人知道为什么会这样吗?我该如何在循环中运行它?
= = = = =
编辑:正如评论中指出的那样,我的问题有点令人困惑,所以我将尝试在这里澄清……
G.playerStatsDifference
的值应该跟踪G.playerStats
的前一个值与G.playerStats
的当前值之间的差值。
为此,我将oldPlayerStats
的值设置为等于G.playerStats
,然后将G.playerStats
更新为其新值。
然后我需要遍历对象数组并从oldPlayerStats
中减去G.playerStats
的值。这将产生G.playerStatsDifference
的值这就是循环的作用,遍历每个对象键并进行计算。
希望这能提供一些清晰。对不起,我的问题写得不好。
const diffBetweenObjectValues = (a, b) => {
return Object.entries(a).reduce((result, [aKey, aVal]) => {
result[aKey] = aVal - (b[aKey] ?? 0);
return result;
}, {});
}
const stats = { a: 1, b: 2 };
const updatedStats = { a: 1, b: 1 };
// Initial player stats are { a: 1, b: 2 }
const player = { stats: stats, diff: {} };
// Set the diff, value is { a: 0, b: 1 }
player.diff = diffBetweenObjectValues(player.stats, updatedStats);
// Actually update the stats, value is { a: 1, b: 1 }
player.stats = updatedStats;
注意,如果一个键在b
中存在,但在a
中不存在,它将被忽略。还要注意,如果所有的属性值都是数字,那么只有才能正常工作。
你可以把状态转换放在一个函数中,只在你需要更新状态时运行它(就像游戏循环的每一次滴答)。
对评论的回应
好,让我们添加另一个辅助函数
const zip = (a, b) => a.map((x, i) => [x, b[i]]);
const players = [...]; // array of players
const statUpdates = [...]; // array of stat updates
zip(players, statUpdates).forEach(([player, stats]) => {
player.diff = diffBetweenObjectValues(player.stats, stats);
player.stats = stats;
});
Zip将玩家数组和状态更新数组成对地组合在一起,然后使用forEach
对它们进行迭代,解构比特,并运行更新。你也可以只使用for循环,它更快,但更难阅读,更容易出错(例如off-by- 1错误)。我会坚持使用这个版本,除非你的分析器告诉你它太慢了。
更新2
const currentStats = [{ a: 1, b: 2 }, {a: 3, b: 2 }];
const updatedStats = [{ a: 0, b: 1 }, {a: 4, b: 1 }];
const diffedStats = zip(currentStats, updatedStats).map(([current, updated]) => {
return diffBetweenObjectValues(current, updated);
});
// for testing purposes, create an object with some random stats
const randomPlayerStats = () => Object.fromEntries(
['carpenter','wood','gunman','gunpowder','merchant','gold','fleet','flagship']
.map(k=>[k,Math.random()*10|0]));
// array of the last player stats recorded for each player
let lastPlayerStats = [];
// create a new object from the existing object, subtracting each entry
// from the old object from the entry from the new object
// note: uses the ?? operator so that if there is no last object yet,
// the last object value will be treated as being zero
const difference = (playerStats, lastPlayerStats) => {
let r = Object.fromEntries(Object.entries(playerStats).map(([k,v])=>
[k, v-(lastPlayerStats?.[k]??0)]));
lastPlayerStats = playerStats;
return r;
};
// simulate 5 rounds of the game, with 2 players in the game
const playerCount = 2;
const simulatedRounds = 5;
for(let c=0;c<simulatedRounds;c++) {
let playerStats = [...Array(playerCount).keys()].map(i=>randomPlayerStats());
let playerStatsDifference = playerStats.map((s,i)=>
difference(s, lastPlayerStats[i]??{}));
console.log('playerStats:');
console.log(playerStats);
console.log('playerStatsDifference:');
console.log(playerStatsDifference);
}