nodeJs+express+soket.io五子棋实战之浏览器兼容性处理

简介: nodeJs+express+soket.io五子棋实战之浏览器兼容性处理

nodeJs+express+soket.io五子棋实战之浏览器兼容性处理

  1. 目录结构:

  2. 演示URL:http://39.96.31.43:3100/
  3. 演示截图
  4. 演示截图2:
  5. 源码展示:
  6. 客户端index.js:
window.onload=function(){
    var sence = document.getElementById('sence'),
        //棋盘大小
        ROW = 20,NUM = ROW*ROW,
        //场景宽度
        senceWidth = sence.offsetWidth,
        //每颗棋子的宽度
        blockWidth = Math.floor( (senceWidth-ROW)/ROW ) + 'px',
         //用户开始默认可以落子
        canDrop = true,
        //用户默认落子为白棋
        color = 'white',
        //两个字典,用来存放白棋和黑棋的已落子的位置;以坐标为建,值为true
        whiteBlocks = {},blackBlocks = {};
        console.log(sence);
//创建场景
(function (){
    var el,
    //在棋盘上画线
        rowline,
        colline;
    for ( var i = 0;i < ROW;i++){
        //按照计算好的间隔放置横线
        rowline = document.createElement('div');
        rowline.setAttribute('class','row');
        rowline.style.top= (senceWidth/ROW)/2 + (senceWidth/ROW)*i + 'px';
        sence.appendChild(rowline);
        //按照计算好的间隔放置竖线
        colline = document.createElement('div');
        colline.setAttribute('class','col');
        colline.style.left= (senceWidth/ROW)/2 + (senceWidth/ROW)*i + 'px';
        sence.appendChild(colline);
        for ( var j = 0;j < ROW;j++){
            el = document.createElement('div');
            el.style.width = blockWidth;
            el.style.height = blockWidth;
            el.setAttribute('class','block');
            el.setAttribute('id',i + '_' + j);
            sence.appendChild(el);
        }
    }
})();
console.log('1')
var id2Position = function(id){
    console.log(id)
    return {x:Number(id.split('_')[0]),y:Number(id.split('_')[1])};
};
var position2Id = function(x,y){
    return x + '_' + y;
};
console.log('abc');
//判断落子皇后该色其是否连5
var isHasWinner = function(id,dic){
    var x = id2Position(id).x;
    var y = id2Position(id).y;
    //用来记录横,竖,左斜,右斜方向的连续棋子数量
    var rowCount = 1,colCout = 1,leftSkewLineCount = 1,righeSkewlineCount = 1;
    //tx ty作为游标,左移,右移,上移,下移,左上,右下,左下,右上移动
    //每次数万某个方向的连续棋子后,游标会回到原点
    var tx,ty;
    //注意:一下判断5连以上不算成功,如果规则有变动,条件改为大于五就可以
    tx = x;ty = y;
    while(dic[ position2Id(tx,ty+1) ]){
        rowCount++;
        ty++;
    }
    tx = x;ty = y;
    while(dic[ position2Id(tx,ty-1) ]){
        rowCount++;
        ty--;
    };
    if( rowCount ==5 ) return true;
    tx = x;ty = y;
    while(dic[ position2Id(tx+1,ty) ]){
        colCout++;
        tx++;
    }
    tx = x;ty = y;
    while(dic[ position2Id(tx-1,ty) ]){
        colCout++;
        tx--;
    };
    if( colCout ==5 ) return true;
    tx = x;ty = y;
    while(dic[ position2Id(tx+1,ty+1) ]){
        leftSkewLineCount++;
        tx++;
        ty++;
    }
    tx = x;ty = y;
    while(dic[ position2Id(tx-1,ty-1) ]){
        leftSkewLineCount++;
        tx--;
        ty--;
    }
    if( leftSkewLineCount == 5){
        return true;
    }
    tx = x;ty = y;
    while(dic[ position2Id(tx-1,ty+1) ]){
        righeSkewlineCount++;
        tx--;
        ty++;
    }
    tx = x;ty = y;
    while(dic[ position2Id(tx+1,ty-1) ]){
        leftSkewLineCount++;
        tx++;
        ty--;
    }
    if( righeSkewlineCount == 5) return true;
    return false;
};
 //处理对手发送过来的信息;
//  var socket = io.connect('http://127.0.0.1:3100'); 
if (/Firefox\/\s/.test(navigator.userAgent)){
    var socket = io.connect('http://127.0.0.1:3100',{transports:['xhr-polling']}); 
} 
else if (/MSIE (\d+.\d+);/.test(navigator.userAgent)){
    var socket = io.connect('http://127.0.0.1:3100',{transports:['jsonp-polling']}); 
} 
else { 
    var socket = io.connect('http://127.0.0.1:3100'); 
}
    socket.on('message',function(data){
        // console.log('data');
        canDrop = true;
        var el = document.getElementById(data.id);
        // console.log(el)
        el.setAttribute('has-one','true');
        if(data.color == 'white'){
            color = 'black';
            el.setAttribute('class','block white');
            whiteBlocks[data.id] = true;
             if(isHasWinner(data.id,whiteBlocks)){
                 alert('白棋赢了');
                 location.reload();//Location.reload() 方法用来刷新当前页面。该方法只有一个参数,当值为 true 时,将强制浏览器从服务器加载页面资源,当值为 false 或者未传参时,浏览器则可能从缓存中读取页面。
             }
            }else{ 
                 el.setAttribute('class','block black');
                 blackBlocks[data.id] = true;
                 if( isHasWinner(data.id,blackBlocks)){
                     alert('黑棋赢了');
                     location.reload();
                 }
             }
        });
        sence.onclick = function(e){ 
            // console.log('gyu')
             var el = e.target;//触发事件的对象 (某个DOM元素) 的引用。当事件处理程序在事件的冒泡或捕获阶段被调用时;
             if( !canDrop || el.hasAttribute('has-one') || el == this){//hasAttributes属性返回一个布尔值true或false,来表明当前元素节点是否有至少一个的属性
                return;
             }
             el.setAttribute('has-one','true');
             canDrop = false;
             var id = el.getAttribute('id');
             if(color == 'white'){
                 el.setAttribute('class','block white');
                 whiteBlocks[id] = true;
                 socket.emit('message',{id:id,color:'white'});//socket.emit('action',data);表示发送了一个action命令,还有data数据,在另一端接收时,可以这么写: socket.on('action',function(data){...});
                 if(isHasWinner(id,whiteBlocks)){
                     alert('白棋赢');
                     location.reload();
                 }
             }
             if( color == 'black'){
                 el.setAttribute('class','block black');
                 blackBlocks[id]=true;
                 socket.emit('message' , {id:id,color:'black'});
                 if(isHasWinner(id,blackBlocks)){
                     alert('黑棋赢了');
                     location.reload();
                 }
             }
     };
};
  1. 样式index.css
body{
    background: #4b4832;
    font-family: 微软雅黑;
    color: #666;
}
.sence{
    width: 600px;
    height: 600px;
    margin: 50px auto;
    border-right: none;
    border-bottom: none;
    position: relative;
    box-shadow: -10px 10px 15px black;
    background: #8d6d45;
    border: 2px solid black;
}
.sence .block{
    float: left;
    margin-right: 1px;
    margin-bottom: 1px;
    border-radius: 50%;
    position: relative;
    z-index: 8884;
}
.sence .row,.sence .col{
    background: #4d392b;
    position: absolute;
}
.sence .row{
    width:100%;
    height: 1px;
    top: 0;
}
.sence .col{
    width:1px;
    height: 100%;
    top: 0;
}
.white{
    background: #ffffff;
}
.black{
    background: #2c1d1b;
}
  1. index.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>五子棋</title>
    <link rel="stylesheet" href="./public/index.css">
</head>
<body>
    <div class="sence" id="sence"></div>
    <script src="/public/socket.io.js"></script>
    <script src="/public/index.js" type="text/javascript" ></script>
</body>
</html>
  1. 服务端index.js
var express = require('express');
var path = require('path');
var app = express()
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.on('connection',function(socket){
    socket.on('message',function(data){
        socket.broadcast.emit('message',data);
    });
});
app.use('/public/',express.static(path.join(__dirname,'./public/')))
app.use('/node_modules/',express.static(path.join(__dirname,'./node_modules/')))
app.get('/',function(req,res){
    res.sendFile(__dirname +  '/index.html');
});
 http.listen(3100,function(){
     console.log('runing...')
 })
  1. socket.io 兼容性代码:
if (/Firefox\/\s/.test(navigator.userAgent)){
    var socket = io.connect('http://127.0.0.1:3100',{transports:['xhr-polling']}); 
} 
else if (/MSIE (\d+.\d+);/.test(navigator.userAgent)){
    var socket = io.connect('http://127.0.0.1:3100',{transports:['jsonp-polling']}); 
} 
else { 
    var socket = io.connect('http://127.0.0.1:3100'); 
}
相关文章
|
30天前
|
JavaScript 前端开发 中间件
探索后端技术:Node.js与Express框架的完美融合
【10月更文挑战第7天】 在当今数字化时代,Web应用已成为日常生活不可或缺的一部分。本文将深入探讨后端技术的两大重要角色——Node.js和Express框架,分析它们如何通过其独特的特性和优势,为现代Web开发提供强大支持。我们将从Node.js的非阻塞I/O和事件驱动机制,到Express框架的简洁路由和中间件特性,全面解析它们的工作原理及应用场景。此外,本文还将分享一些实际开发中的小技巧,帮助你更有效地利用这些技术构建高效、可扩展的Web应用。无论你是刚入门的新手,还是经验丰富的开发者,相信这篇文章都能为你带来新的启发和思考。
|
9天前
|
JavaScript 中间件 关系型数据库
构建高效的后端服务:Node.js 与 Express 的实践指南
在后端开发领域,Node.js 与 Express 的组合因其轻量级和高效性而广受欢迎。本文将深入探讨如何利用这一组合构建高性能的后端服务。我们将从 Node.js 的事件驱动和非阻塞 I/O 模型出发,解释其如何优化网络请求处理。接着,通过 Express 框架的简洁 API,展示如何快速搭建 RESTful API。文章还将涉及中间件的使用,以及如何结合 MySQL 数据库进行数据操作。最后,我们将讨论性能优化技巧,包括异步编程模式和缓存策略,以确保服务的稳定性和扩展性。
|
10天前
|
网络协议 物联网 API
Python网络编程:Twisted框架的异步IO处理与实战
【10月更文挑战第26天】Python 是一门功能强大且易于学习的编程语言,Twisted 框架以其事件驱动和异步IO处理能力,在网络编程领域独树一帜。本文深入探讨 Twisted 的异步IO机制,并通过实战示例展示其强大功能。示例包括创建简单HTTP服务器,展示如何高效处理大量并发连接。
32 1
|
16天前
|
Web App开发 JavaScript 中间件
构建高效后端服务:Node.js与Express框架的完美结合
【10月更文挑战第21天】本文将引导你走进Node.js和Express框架的世界,探索它们如何共同打造一个高效、可扩展的后端服务。通过深入浅出的解释和实际代码示例,我们将一起理解这一组合的魅力所在,并学习如何利用它们来构建现代Web应用。
38 1
|
4天前
|
Web App开发 JavaScript 前端开发
探索后端开发:Node.js与Express的完美结合
【10月更文挑战第33天】本文将带领读者深入了解Node.js和Express的强强联手,通过实际案例揭示它们如何简化后端开发流程,提升应用性能。我们将一起探索这两个技术的核心概念、优势以及它们如何共同作用于现代Web开发中。准备好,让我们一起开启这场技术之旅!
13 0
|
4天前
|
Web App开发 JavaScript 前端开发
构建高效后端服务:Node.js与Express框架的实践
【10月更文挑战第33天】在数字化时代的浪潮中,后端服务的效率和可靠性成为企业竞争的关键。本文将深入探讨如何利用Node.js和Express框架构建高效且易于维护的后端服务。通过实践案例和代码示例,我们将揭示这一组合如何简化开发流程、优化性能,并提升用户体验。无论你是初学者还是有经验的开发者,这篇文章都将为你提供宝贵的见解和实用技巧。
|
5天前
|
Web App开发 JavaScript 中间件
构建高效后端服务:Node.js与Express框架的融合之道
【10月更文挑战第31天】在追求快速、灵活和高效的后端开发领域,Node.js与Express框架的结合如同咖啡遇见了奶油——完美融合。本文将带你探索这一组合如何让后端服务搭建变得既轻松又充满乐趣,同时确保你的应用能够以光速运行。
11 0
|
9天前
|
网络协议 调度 开发者
Python网络编程:Twisted框架的异步IO处理与实战
【10月更文挑战第27天】本文介绍了Python网络编程中的Twisted框架,重点讲解了其异步IO处理机制。通过反应器模式,Twisted能够在单线程中高效处理多个网络连接。文章提供了两个实战示例:一个简单的Echo服务器和一个HTTP服务器,展示了Twisted的强大功能和灵活性。
23 0
|
2月前
|
JavaScript
NodeJs的安装
文章介绍了Node.js的安装步骤和如何创建第一个Node.js应用。包括从官网下载安装包、安装过程、验证安装是否成功,以及使用Node.js监听端口构建简单服务器的示例代码。
NodeJs的安装
|
1月前
|
JavaScript 开发工具 git
已安装nodejs但是安装hexo报错
已安装nodejs但是安装hexo报错
21 2
下一篇
无影云桌面