const express = require('express') const 游戏 = express() 游戏.use(express.static('public')) const 主机 = process.env.HOST || '0.0.0.0' const 端口 = process.env.PORT || 3000 const 服务器 = 游戏.listen(端口, 主机, () => console.log(`小猫钓鱼游戏服务运行在 http://${主机}:${端口}/`)) const IO = require('socket.io')(服务器) const clients = [] // 所有客户 const players = [] // 所有玩家 let cardsOnTable = [] // 桌上的牌 let currentPlayerNumber = -1 // 当前玩家序号 IO.on('connection', (client) => { addClient(client) client.on('disconnect', () => removeClient(client)) client.on('join', () => playerJoin(client)) client.on('go', () => go(client)) }) function addClient(client) { client.cards = [] clients.push(client) IO.emit('onlineNumber', clients.length) client.emit('playersNumber', players.length) client.emit('join', 0) gameStatus() // TODO:只告诉当前加入的客户端 console.info(`新客户端已连接,当前客户端${clients.length}个`) } function removeClient(client) { let index = clients.indexOf(client) clients.splice(index, 1) IO.emit('onlineNumber', clients.length) console.log(`已断开,当前客户端${clients.length}个`) if (players.includes(client)) { index = players.indexOf(client) players.splice(index, 1) IO.emit('playersNumber', players.length) // 游戏被迫结束? if (players.length == 2) { gameFinished() IO.emit('alert', `玩家${index + 1}掉线了`) } } } function playerJoin(player) { if (players.length < 3) { let playerIndex = players.indexOf(player) let playerNumber = playerIndex + 1 if (playerNumber > 0) { playerNumber = 0 players.splice(playerIndex, 1) console.log(`玩家${playerNumber} 已退出,当前玩家数:${players.length}`) } else { players.push(player) playerNumber = players.indexOf(player) + 1 console.log(`玩家${playerNumber} 已加入,当前玩家数:${players.length}`) player.cards = [] if (players.length === 3) gameStart() } player.emit('join', playerNumber) IO.emit('playersNumber', players.length) } } function gameStart() { console.log('游戏开始') cardsOnTable.length = 0 currentPlayerNumber = 0 // 洗牌,每玩家发18张 const drawer = [ { color: '♠️', value: '2' }, { color: '♠️', value: '3' }, { color: '♠️', value: '4' }, { color: '♠️', value: '5' }, { color: '♠️', value: '6' }, { color: '♠️', value: '7' }, { color: '♠️', value: '8' }, { color: '♠️', value: '9' }, { color: '♠️', value: '10' }, { color: '♠️', value: 'J' }, { color: '♠️', value: 'Q' }, { color: '♠️', value: 'K' }, { color: '♠️', value: 'A' }, { color: '♥️', value: '2' }, { color: '♥️', value: '3' }, { color: '♥️', value: '4' }, { color: '♥️', value: '5' }, { color: '♥️', value: '6' }, { color: '♥️', value: '7' }, { color: '♥️', value: '8' }, { color: '♥️', value: '9' }, { color: '♥️', value: '10' }, { color: '♥️', value: 'J' }, { color: '♥️', value: 'Q' }, { color: '♥️', value: 'K' }, { color: '♥️', value: 'A' }, { color: '♣️', value: '2' }, { color: '♣️', value: '3' }, { color: '♣️', value: '4' }, { color: '♣️', value: '5' }, { color: '♣️', value: '6' }, { color: '♣️', value: '7' }, { color: '♣️', value: '8' }, { color: '♣️', value: '9' }, { color: '♣️', value: '10' }, { color: '♣️', value: 'J' }, { color: '♣️', value: 'Q' }, { color: '♣️', value: 'K' }, { color: '♣️', value: 'A' }, { color: '♦️', value: '2' }, { color: '♦️', value: '3' }, { color: '♦️', value: '4' }, { color: '♦️', value: '5' }, { color: '♦️', value: '6' }, { color: '♦️', value: '7' }, { color: '♦️', value: '8' }, { color: '♦️', value: '9' }, { color: '♦️', value: '10' }, { color: '♦️', value: 'J' }, { color: '♦️', value: 'Q' }, { color: '♦️', value: 'K' }, { color: '♦️', value: 'A' }, { color: '小', value: 'Joker' }, { color: '大', value: 'Joker' }, ] while (drawer.length > 0) { let index = Math.floor(Math.random() * drawer.length) let card = drawer[index] players[currentPlayerNumber].cards.push(card) drawer.splice(index, 1) currentPlayerNumber = (currentPlayerNumber + 1) % 3 } gameStatus() } function gameStatus() { const cardsNumbers = [] for (let player of players) { cardsNumbers.push(player.cards.length) } const cardsStrings = [] for (let card of cardsOnTable) { cardsStrings.push(`[${card.color}${card.value}]`) } IO.emit('status', { players: cardsNumbers, cards: cardsStrings.join(''), current: currentPlayerNumber, }) } function go(client) { if (currentPlayerNumber != -1 && players.indexOf(client) === currentPlayerNumber) { let card = players[currentPlayerNumber].cards[0] players[currentPlayerNumber].cards.splice(0, 1) console.log(`玩家${currentPlayerNumber + 1} 出牌 [${card.color} ${card.value}]`) // 判断有没有钓到 let i = 0 let getit = false for (i = 0; i < cardsOnTable.length; i++) { if (cardsOnTable[i].value == card.value) { getit = true break } } if (getit) { // 将第i张牌后面的牌和玩家刚出的牌一起拿走放回玩家手中的牌后面 const fishes = [...cardsOnTable.slice(i), card] console.log(`玩家${currentPlayerNumber + 1} 钓到 ${fishes.length} 条鱼`) players[currentPlayerNumber].cards = players[currentPlayerNumber].cards.concat(fishes) cardsOnTable = cardsOnTable.slice(0, i) } else { cardsOnTable.push(card) if (players[currentPlayerNumber].cards.length == 0) { client.emit('alert', '你输了') } currentPlayerNumber = (currentPlayerNumber + 1) % 3 while (players[currentPlayerNumber].cards.length == 0) { currentPlayerNumber = (currentPlayerNumber + 1) % 3 } } gameStatus() // 游戏结束了? let looser = 0 let winner = 0 for (let index = 0; index < players.length; index++) { const player = players[index] if (player.cards.length == 0) looser++ else winner = index + 1 } if (looser >= 2) { gameFinished() players[index].emit('alert', '你赢了!') players[index].broadcast.emit('alert', `玩家${winner} 获胜了!`) } } } function gameFinished() { players.length = 0 cardsOnTable.length = 0 currentPlayerNumber = -1 IO.emit('join', 0) IO.emit('playersNumber', 0) IO.emit('status', { players: [0, 0, 0], cards: '', current: currentPlayerNumber }) }