【发布时间】:2021-06-16 08:06:23
【问题描述】:
我正在尝试开发一款游戏,在其中的一轮中,每个玩家都有不同的玩家作为他们的目标。
这是我的逻辑:我对我的玩家集合执行 .onSnapshot() 以实时获取我的数据。
然后对于每个玩家,我执行 Math.floor(Math.random()*players.length) 来为我的玩家获取随机目标。然后我做一个检查:
玩家是把自己作为他们的目标还是已经是某人的目标? => 寻找新目标
否则将目标分配给玩家。 (也在firebase中将目标的isATarget设置为true) 对所有其他玩家重复。
现在我对这种方法有 2 个问题:
如果有 4 个玩家(a、b、c、d),那么可能 a 有 b,b 有 c,c 有 a,d 永远找不到目标,导致函数永远循环。
我遇到的另一个问题是我的播放器数组没有实时更新。因此代码无法检测到某人的 isATarget 何时设置为 true。
这是我的源代码:
import { useEffect, useState } from "react"
import { useLocation } from "react-router"
import { db } from "../../services/firestore"
const Round2Info = () => {
const [players, setPlayers] = useState([]);
const [foundPlayers, setFoundPlayers] = useState(false)
const location = useLocation();
useEffect(() => {
if (location.state.you.host === true) { // so only 1 person in the lobby is executing this code
console.log('Step 1: code is only accessable by host');
// get players
db.collection("GameLobbies").doc(location.state.lobby.id).collection("players").onSnapshot((snapshot) => {
let playersArr = players;
console.log('getting players in round2info');
const changes = snapshot.docChanges();
changes.forEach(change => {
if (change.type === 'added') {
playersArr.push(change.doc.data());
}
})
setPlayers([...playersArr]);
setFoundPlayers(true);
});
}
}, []);
useEffect(() => {
if(foundPlayers){
console.log('foundPlayers is true so', players); // this works. it shows all players
givePlayersTheirTarget();
}
},[foundPlayers])
const givePlayersTheirTarget = () => {
console.log('Step 2: every player,', players, 'foreach'); // works
players.forEach(player => {
givePlayerTheirTarget(player)
})
}
const givePlayerTheirTarget = player => {
console.log('Step 3: player get their target');
let target = getRandomPlayer();
if (target.id === player.id || target.isATarget === true) {
console.log(player.name, 'cant have', target.name, 'as their target');
givePlayerTheirTarget(player);
} else {
console.log(player.name, 'has', target.name, 'as their target');
// set target's isATarget to true
db.collection("GameLobbies").doc(location.state.lobby.id).collection("players").doc(target.id).update({
isATarget: true
});
// assign target to person
db.collection("GameLobbies").doc(location.state.lobby.id).collection("players").doc(player.id).update({
round2Target: target.name
})
console.log(players); // player who's been picked as a target stills shows isATarget = false while it should be true by now
}
}
const getRandomPlayer = () => {
return players[Math.floor(Math.random() * players.length)];
}
return (
<div className="container">
round 2 info
</div>
)
}
export default Round2Info
【问题讨论】: