Node.js开发多人井字棋第二个客户端turn变量不更新问题
核心问题
- 你的
main.js中socket.on('move')回调的参数turn和全局的turn变量重名,回调内修改的是局部参数,全局的回合状态根本没有更新,导致第二个窗口落子时始终读取初始值turn=0,只会放置X。 - 所有游戏状态(落子记录、回合信息)仅在操作的客户端本地更新,接收消息的客户端没有同步这些状态,后续的胜负判定也会出错。
- 服务端没有存储全局游戏状态,新用户加入或页面刷新后状态会完全不一致。
修改方案
1. 调整server.js,增加全局状态存储和同步逻辑
const express = require('express'); const app = express(); const server = require('http').createServer(app); const io = require('socket.io')(server, {cors: {origin: "*"}}); app.use(express.static(__dirname + '/public')); // 服务端全局存储游戏状态 let gameState = { turn: 0, placed: Array(9).fill(""), playerOnePick: [], playerTwoPick: [] } app.get('/', (req, res) => { res.sendFile("/home/pi/nodeTacTow/index.html"); }) server.listen(3000, () => { console.log("server started at port 3000...") }); io.on('connection', (socket) => { console.log("Welcome MR" + socket.id); socket.join("GameRoom"); // 新连接进来先同步当前游戏状态 socket.emit('syncState', gameState); socket.on('move', (moveOne, turn) => { // 服务端更新全局状态 gameState.turn = turn; gameState.placed[moveOne-1] = moveOne; if(turn === 1) { gameState.playerOnePick.push(moveOne); } else { gameState.playerTwoPick.push(moveOne); } console.log(turn); socket.broadcast.emit('move', moveOne, turn); }); socket.on('win', (player) => { console.log("WINNER IS: " + player); // 对局结束重置服务端状态 gameState = { turn: 0, placed: Array(9).fill(""), playerOnePick: [], playerTwoPick: [] } }); // 同步开局操作 socket.on('startGame', () => { gameState = { turn: 0, placed: Array(9).fill(""), playerOnePick: [], playerTwoPick: [] } socket.broadcast.emit('startGame'); }) })
2. 调整main.js,修复turn更新问题、同步所有游戏状态
var gridOne = document.getElementById('grid-item-one'); var gridTwo = document.getElementById('grid-item-two'); var gridThree = document.getElementById('grid-item-three'); var gridFour = document.getElementById('grid-item-four'); var gridFive = document.getElementById('grid-item-five'); var gridSix = document.getElementById('grid-item-six'); var gridSeven = document.getElementById('grid-item-seven'); var gridEight = document.getElementById('grid-item-eight'); var gridNine = document.getElementById('grid-item-nine'); var gridArray = [gridOne, gridTwo, gridThree, gridFour, gridFive, gridSix, gridSeven, gridEight, gridNine]; const socket = io('http://192.168.10.130:3000/') var cell = []; var playerOnePick = []; var playerTwoPick = []; var textField = document.getElementById('text-field'); var turn = 0; var placed = ["", "", "", "", "", "", "", "", ""]; function placeBet(place, numb){ var player; var name; if(turn === 0 && place.innerHTML === ""){ playerOnePick.push(numb); place.innerHTML = '<h1 class="gameX">X</h1>'; turn = 1; textField.innerHTML= "Player 2's turn"; player = playerOnePick; name = "PLAYER ONE"; } else if(turn === 1 && place.innerHTML === ""){ playerTwoPick.push(numb); place.innerHTML = '<h1 class="gameO">O</h1>'; turn = 0; textField.innerHTML= "Player 1' turn"; player = playerTwoPick; name = "PLAYER TWO" } socket.emit('move', numb, turn); placed[numb - 1] = numb; console.log("Player one picked: " + playerOnePick + " Player two picked: " + playerTwoPick); checkWin(player, name); } var a; var b; var c; function checkWin(player, name){ var valueOne = '<h1 class="gameO">O</h1>'; var valueTwo = '<h1 class="gameX">X</h1>'; var winCombos = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 4, 7], [2, 5, 8], [3, 6, 9], [1, 5, 9], [3, 5, 7] ]; for(var i = 0; i < winCombos.length; i++){ const winCondition = winCombos[i]; a = winCondition[0]; b = winCondition[1]; c = winCondition[2]; if (a === '' || b === '' || c === '') { continue; } if (player.includes(a) && player.includes(b) && player.includes(c)) { textField.innerHTML = name + " IS THE WINNER"; socket.emit("win", name); break; } } } function startGame(){ playerOnePick=[]; playerTwoPick=[]; textField.innerHTML="Player 1's turn"; turn = 0; placed = Array(9).fill(""); // 通知服务端和其他客户端重置对局 socket.emit('startGame'); for(var i = 0; i < gridArray.length; i++){ gridArray[i].innerHTML = ""; } } socket.on("connection", () => { console.log("Welcome") }); // 修复turn更新问题,同步落子记录 socket.on('move', (number, serverTurn) => { // 直接更新全局turn变量 turn = serverTurn; if(turn === 1){ gridArray[number-1].innerHTML='<h1 class="gameX">X</h1>'; textField.innerHTML="Player 2's turn"; playerOnePick.push(number); } else if(turn === 0){ gridArray[number-1].innerHTML='<h1 class="gameO">O</h1>'; textField.innerHTML="Player 1's turn"; playerTwoPick.push(number); } placed[number-1] = number; }) socket.on('win', (name) => { textField.innerHTML= name + "IS THE WINNER!"; }) // 新加入对局同步当前状态 socket.on('syncState', (state) => { turn = state.turn; placed = state.placed; playerOnePick = state.playerOnePick; playerTwoPick = state.playerTwoPick; // 同步渲染棋盘 playerOnePick.forEach(num => { gridArray[num-1].innerHTML='<h1 class="gameX">X</h1>'; }) playerTwoPick.forEach(num => { gridArray[num-1].innerHTML='<h1 class="gameO">O</h1>'; }) textField.innerHTML = turn === 0 ? "Player 1's turn" : "Player 2's turn"; }) // 同步其他客户端的开局操作 socket.on('startGame', () => { startGame(); })
内容的提问来源于stack exchange,提问作者catfish
相关产品推荐
相关产品推荐

