node.js利用socket.io实现多人在线匹配联机五子棋

项目地址,已上传github ——>

client端使用简单的h5+js实现了棋局的总体布局。 server端使用node的socket.io模块与客户端进行数据交互,棋子的落点和输赢校验均是在server端完成。

五子棋ui界面请见..

client端的界面这里就不做过多解释了,只要稍微懂点h5就可以自行去这里 下载源代码观看,因为今天的主题主要是socket.io这一块,所以本章只概述client和server是如何通过tcp连接进行交互的。

首先先带大家看一下目录结构

| server.js (socket服务器)
| gobang-ui.html (是玩家下棋页面)
| index.html (是用户登陆界面)
| home.html (是用户大厅界面, 用来匹配等待的 如果在线人数少于2人, 则匹配失败, 并会返回错误信息)
| game.html (client端程序的入口,内嵌iframe来显示各个页面,通过改变iframe的src属性,来达成伪页面跳转)
| img (图片资源文件夹)
| tou.jpg (棋盘界面用户的头像,因为登录界面只要输入用户名就可以开始游戏了,所以所有用户的头像都是一样的)

game.html主界面

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
 <style>
 * {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
 }
 </style>
 <!-- 引入cdn上的socket.io库 -->
 <script src="https://cdn.bootcss.com/socket.io/2.1.0/socket.io.js"></script>
</head>
<body>
<!-- 这里是程序的入口,通过js改变src属性,来切换页面 -->
<iframe id="game" src="index.html" width="100%" height="100%" scrolling="no"></iframe>
</body>
</html>

为什么我们要用嵌入iframe改变src属性的方式来制造页面跳转的现象?因为页面的每一次跳转或刷新都会使socket连接断开。就好像http中的request请求一样,页面每次所以我们应尽量避免页面跳转这个操作。

// 这行代码表示client端对server端进行第一次连接
var socket = io('ws://localhost:3000')

在index.html也就是用户的登录界面

<!-- 这是用户登录的按钮 -->
<div onclick="login()">开始游戏</div>

当点击了这个按钮之后,它会触发js中的login方法,但这个方法并不会直接去连接server,因为socket连接在game.html中,所以目前来看,这个页面只是game.html的子页面,这个方法在判断input中的value是否为空后,立即通过全局对象parent调用的父页面(game.html)中的login方法

// index.html中的login方法
function login() {
 if (username.value === undefined || username.value === '') {
  return
 }
 // 调用父窗口的login方法
 parent.login(username.value)
}

game.html中的login方法,这个方法通过socket向server触发了login事件

function login(username) {
 socket.emit('login', username)
}

server.js

// 监听连接
io.on('connection', function (socket) {
 // 玩家登陆, socket.emit('login', username)就是触发了这个事件
 // 监听了login事件
 socket.on('login', function (name) {
 // players是一个全局数组,里面存放了所有的玩家对象,如果players中
 var flag = players.some(function (value) {
  return value.name === name
 })
 if (flag) {
  socket.emit('home', {'flag': true})
 } else {
  console.log(name + '已登陆')
  // 创建玩家
  new Player(socket, name)
  // 将玩家放进数组中
  // players.push(player)
  // 如果用户名没有重名,那么触发client端的home事件
  socket.emit('home', {'playerCount': playerCount, 'name': name})
 }
 })
})

玩家client对home事件的监听

// 玩家登陆成功
 socket.on('home', function (data) {
 if (data.flag) {
  game.contentWindow.flag.hidden = false
 } else {
  game.contentWindow.flag.hidden = true
  // 保存用户名和玩家在线人数到localStorage中
  localStorage.setItem('name', data.name)
  localStorage.setItem('playerCount', data.playerCount)
  // location.href = './home.html'
  game.src = 'home.html'
 }
 })

home.html玩家等待大厅, home.html和index.html长得基本一致,所以它也有一个按钮,匹配按钮,通过它来触发play事件

// 玩家开始匹配
 this.socket.on('play', function () {
 // 如果空闲玩家总数大于或等于2,那么开始游戏
 if (playerCount >= 2) {
  self.pipei = true
  // 如果已经有人在开始匹配了,那么这个玩家就不需要走下面函数了,因为继续执行的话相当于再开一个棋局
  if (isExistFZ(self) > 0) {
  // 保持不动就好,房主会自动找到你的
  return
  }
  // 如果没有房主,那么这个玩家将成为房主
  self.fz = true
  // 可用的玩家数
  var player2 = null
  self.timer = setInterval(function () {
  console.log('正在匹配...')
  if (player2 = findPlayer(self)) {
   console.log('匹配成功')
   self.gamePlay = new Game(self, player2)
   player2.gamePlay = self.gamePlay
   clearInterval(self.timer)
  }
  }, 1000)
 } else {
  socket.emit('player less')
 }
 })

server.js中有两个类,一个是Player玩家类,另一个是Game棋局类,一个棋局对应两个玩家。

Player类的属性

this.socket = socket // socket对象,玩家通过它来监听数据
 this.name = name // 玩家的名称
 this.color = null // 玩家棋子的颜色
 this.state = 0 // 0代表空闲, 1在游戏中
 this.pipei = false // 是否在匹配
 this.gamePlay = null // 棋局对象
 this.flag = true // 是否轮到这个玩家出棋
 this.fz = false // 是否是房主

Player类对象监听的事件

// 监听玩家是否退出游戏
 this.socket.on('disconnect', function () {
  // 删除数组中的玩家
  // players.splice(players.indexOf(self), 1) // 删不掉
  // delete players[players.indexOf(self)]
  // 新的删除方式
  players = players.filter(function (value) {
   return value.name !== self.name
  })
  playerCount--
  // 如果退出游戏的玩家正在进行游戏,那么这局游戏也该退出
  if (self.state === 0) {
   gameCount--
  }
  console.log(self.name + '已退出游戏')
 })
 // 玩家开始匹配
 this.socket.on('play', function () {
  // 如果空闲玩家总数大于或等于2,那么开始游戏
  if (playerCount >= 2) {
   self.pipei = true
   // 如果已经有人在开始匹配了,那么这个玩家就不需要走下面函数了,因为继续执行的话相当于再开一个棋局
   if (isExistFZ(self) > 0) {
    // 保持不动就好,房主会自动找到你的
    return
   }
   // 如果没有房主,那么这个玩家将成为房主
   self.fz = true
   // 可用的玩家数
   var player2 = null
   self.timer = setInterval(function () {
    console.log('正在匹配...')
    if (player2 = findPlayer(self)) {
     console.log('匹配成功')
     self.gamePlay = new Game(self, player2)
     player2.gamePlay = self.gamePlay
     clearInterval(self.timer)
    }
   }, 1000)
  } else {
   socket.emit('player less')
  }
 })
 // 玩家取消匹配按钮
 this.socket.on('clearPlay', function () {
  clearInterval(self.timer)
 })
  // 监听数据,玩家下棋的时候触发
 this.socket.on('data', function (data) {
  if (self.flag) {
   add_pieces(self.gamePlay, data, self.color)
  }
 })
 // 最后将当前玩家实例放到players全局玩家数组中去
 players.push(this)

Game(棋局类)

// 棋盘的格子数
  this.column = 21
  this.arr = init_arr() // 存储棋盘坐标的二位数组
  // 一局棋局上的两个玩家
  this.play1 = play1
  this.play2 = play2
  // 修改游戏状态
   this.play1.state = 1
   this.play2.state = 1
   // 在游戏中,是否匹配为false
   this.play1.pipei = false
   this.play2.pipei = false
   this.play1.fz = false
   this.play1.fz = false
   // 随机给两个玩家分配棋子颜色
   this.play1.color = ~~(Math.random() * 2) === 0 ? 'white' : 'black'
   this.play2.color = this.play1.color === 'white' ? 'black' : 'white'
   // 谁是白棋谁先走
   this.play1.flag = this.play1.color === 'white'? true: false
   this.play2.flag = this.play2.color === 'white'? true: false

添加棋子方法

// 添加棋子
function add_pieces(self, position, color) {
 if (self.arr[position.x][position.y] === undefined) {
  self.arr[position.x][position.y] = color
  if (color === self.play1.color) {
   self.play1.flag = false
   self.play2.flag = true
  } else if (color === self.play2.color) {
   self.play1.flag = true
   self.play2.flag = false
  }
  check_result(self, self.arr, position, color)
 }
}
// 初始化数组
function init_arr() {
 var arr = []
 for (var i = 0; i < 21; i++) {
  arr.push(new Array(21))
 }
 return arr
}

如果大家喜欢的话,请在github上下载我的源码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • JavaScript实现五子棋游戏的方法详解

    本文实例讲述了JavaScript实现五子棋游戏的方法.分享给大家供大家参考,具体如下: 最近半个月一直在看深入的学习JavaScript,里面有很多重点和难点,比如闭包.词法分析.面向对象等.今天给大家分享一个由JavaScript编写的五子棋游戏,主要用到JavaScript的面向对象.事件委托.闭包等知识,还是挺有分量的,正好可以检测学习的成果. 老规矩,先上图,再说话. 效果图: 五子棋素材图: 代码: <!DOCTYPE html> <html> <head>

  • 基于JavaScript实现五子棋游戏

    本文实例为大家分享了js实现五子棋的具体代码,供大家参考,具体内容如下 思路: 1.先用canvas画五子棋的棋盘 2.获取鼠标点击的位置 3.根据鼠标点击的位置判断,并画棋子 4.根据下的棋子判断是否赢了 代码: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style>

  • 原生JS+Canvas实现五子棋游戏实例

    一.功能模块 先看下现在做完的效果: 线上体验:https://wj704.github.io/five_game.html 主要功能模块为: 1.人机对战功能 2.悔棋功能 3.撤销悔棋功能 二.代码详解 2.1 人机对战功能实现 从效果图可以看到,棋盘的横竖可以放的位置为15*15,通过canvas画棋盘: //绘画棋盘 var drawChessBoard = function(){ for(var i = 0; i < 15; i++){ context.moveTo(15 + i *

  • H5+C3+JS实现双人对战五子棋游戏(UI篇)

    本篇文章实现的是双人对战模式,主要是实现除人机AI算法和判断输赢之外的其他功能,下一篇将会发布AI 框架搭建 <!Doctype html> <html> <head> <!-- 百度爬虫优化 --> <meta http-equiv="author" content="成兮,缘分五月" /> <meta http-equiv="Keywords" cotent="五子棋

  • 原生JS+Canvas实现五子棋游戏

    本文实例为大家分享了JS  Canvas实现五子棋游戏的具体代码,供大家参考,具体内容如下 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>五子棋</title> <style type='text/css'> canvas { display: block; margin: 50px auto; box-shadow: -2p

  • JS canvas绘制五子棋的棋盘

    本文为大家分享了JS canvas绘制五子棋棋盘的具体代码,供大家参考,具体内容如下 box-shadow:给元素块周边添加阴影效果. 语法:box-shadow: h-shadow v-shadow blur spread color inset: h-shadow: (必须)阴影的水平偏移量,如果是正值,则阴影在元素块右边:如果是负值,则阴影在元素块左边. v-shadow: (必须)阴影的垂直偏移量,如果是正值,则阴影在元素块底部:如果是负值,则阴影在元素块顶部. blur: (可选)阴影

  • javascript 初学教程及五子棋小程序的简单实现

    一.JavaScript简介 JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能. 二.hbulider工具的使用 1) hbulider的特点: 1.飞快的编码速度 2.HBuilder直接创建移动App,打包为ios或Android原生安装包 3.HTML5语法.HTML5+

  • 纯JS实现五子棋游戏兼容各浏览器(附源码)

    纯JS五子棋(各浏览器兼容) 效果图:  代码下载 HTML代码 复制代码 代码如下: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html;"> <title>五子棋</title> <link rel="stylesheet" type="text/

  • Javascript和HTML5利用canvas构建Web五子棋游戏实现算法

    这只是一个简单的JAVAscript和HTML5小程序,没有实现人机对战. 五子棋棋盘落子点对应的二维数组.数组的元素对应落子点.比如数组元素值为0表示该元素对应的落子点没有棋子,数组元素值为1表示该元素对应的落子点有白棋子,数组元素值为2表示该元素对应的落子点有黑棋子: 判断五子棋赢棋的算法是通过对五子棋棋盘落子点对应的二维数组的操作来实现的. 判断五子棋赢棋算法 下边的函数可以实现判断五子棋赢棋的算法,也可以按照教材中相应的算法实现. 其中函数的参数xx.yy为数组下标,chess数组实现五

  • JS+canvas实现的五子棋游戏【人机大战版】

    本文实例讲述了JS+canvas实现的五子棋游戏.分享给大家供大家参考,具体如下: 运行效果图: html代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>五子棋</title> <link rel="stylesheet" type="text/css" href="css

  • H5+C3+JS实现五子棋游戏(AI篇)

    本文实例为大家分享了H5+C3+JS实现五子棋游戏的具体代码,供大家参考,具体内容如下 新增全局变量 <script> //所有赢法总和 var count = 0; //容纳所有赢法的三维数组 var allWin = []; for(var i =0; i <15; i++){ allWin[i] = []; for(var j=0; j <15; j++){ allWin[i][j] = []; } } //横线赢法 for(var i =0; i <15; i++){

随机推荐