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'); 
}
相关文章
|
2月前
|
Web App开发 JSON JavaScript
Node.js 中的中间件机制与 Express 应用
Node.js 中的中间件机制与 Express 应用
|
2月前
|
缓存 负载均衡 JavaScript
构建高效后端服务:Node.js与Express框架实践
在数字化时代的浪潮中,后端服务的重要性不言而喻。本文将通过深入浅出的方式介绍如何利用Node.js及其强大的Express框架来搭建一个高效的后端服务。我们将从零开始,逐步深入,不仅涉及基础的代码编写,更会探讨如何优化性能和处理高并发场景。无论你是后端新手还是希望提高现有技能的开发者,这篇文章都将为你提供宝贵的知识和启示。
|
2月前
|
JavaScript
使用node.js搭建一个express后端服务器
Express 是 Node.js 的一个库,用于搭建后端服务器。本文将指导你从零开始构建一个简易的 Express 服务器,包括项目初始化、代码编写、服务启动与项目结构优化。通过创建 handler 和 router 文件夹分离路由和处理逻辑,使项目更清晰易维护。最后,通过 Postman 测试确保服务正常运行。
119 1
|
2月前
|
Web App开发 JavaScript 前端开发
探索后端开发:Node.js与Express的完美结合
【10月更文挑战第33天】本文将带领读者深入了解Node.js和Express的强强联手,通过实际案例揭示它们如何简化后端开发流程,提升应用性能。我们将一起探索这两个技术的核心概念、优势以及它们如何共同作用于现代Web开发中。准备好,让我们一起开启这场技术之旅!
68 0
|
2月前
|
Web App开发 JavaScript 前端开发
构建高效后端服务:Node.js与Express框架的实践
【10月更文挑战第33天】在数字化时代的浪潮中,后端服务的效率和可靠性成为企业竞争的关键。本文将深入探讨如何利用Node.js和Express框架构建高效且易于维护的后端服务。通过实践案例和代码示例,我们将揭示这一组合如何简化开发流程、优化性能,并提升用户体验。无论你是初学者还是有经验的开发者,这篇文章都将为你提供宝贵的见解和实用技巧。
|
存储 JavaScript 前端开发
io.js和node.js怎么了?
很多人都问我最近关于io.js和它与Node Forwar、 Advisory Board 和 npm的关系。 这是我个人的观点。我已经和io.js技术委员会分享了这篇文章的草稿,以确保它至少接近他们团队对这个事情的看法
213 0
|
14天前
|
JavaScript
nodejs安装之npm ERR! code CERT_HAS_EXPIREDnpm ERR! errno CERT_HAS_EXPIRED reason: certificate has expired-证书错误通用问题解决方案-优雅草央千澈
nodejs安装之npm ERR! code CERT_HAS_EXPIREDnpm ERR! errno CERT_HAS_EXPIRED reason: certificate has expired-证书错误通用问题解决方案-优雅草央千澈
|
2月前
|
Web App开发 JavaScript 前端开发
2024年5月node.js安装(winmac系统)保姆级教程
本篇博客为2024年5月版Node.js安装教程,适用于Windows和Mac系统。作者是一名熟悉JavaScript与Vue的大一学生,分享了Node.js的基本介绍、下载链接及简单安装步骤。安装完成后,通过终端命令`node -v`验证版本即可确认安装成功。欢迎关注作者,获取更多技术文章。
39 2
2024年5月node.js安装(winmac系统)保姆级教程
|
2月前
|
存储 JavaScript 搜索推荐
Node框架的安装和配置方法
安装 Node 框架是进行 Node 开发的第一步,通过正确的安装和配置,可以为后续的开发工作提供良好的基础。在安装过程中,需要仔细阅读相关文档和提示,遇到问题及时解决,以确保安装顺利完成。
150 2
|
4月前
|
JavaScript
NodeJs的安装
文章介绍了Node.js的安装步骤和如何创建第一个Node.js应用。包括从官网下载安装包、安装过程、验证安装是否成功,以及使用Node.js监听端口构建简单服务器的示例代码。
NodeJs的安装

热门文章

最新文章