本文实例为大家分享了Node.js+Socket.io实现双人在线五子棋对战的具体代码,供大家参考,具体内容如下
笔者建议读者在尝试写程序之前要先确保电脑已经安装了Node.js和NPM,一般两者都是在一块安装,五子棋程序的服务器端使用Node.js写的,不多说了,直接上代码。
服务器端代码:socket.js
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');
app.listen(80);
function handler (req, res) {
fs.readFile(__dirname + '/wzq.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading wzq.html');
}
res.writeHead(200);
res.end(data);
});
}
//io.set('log level',1);
var users = {};
io.on('connection',function(socket){
io.sockets.emit('connect',{con:'connected'});
socket.on('location',function(from, to, msg){
if(to in users){
//console.log('to'+to+' '+msg);
users[to].emit('to'+to,msg);
}
});
socket.on('newUser',function(user){
if(user in users){
socket.emit('exist',{})
}
else{
users[user] = socket;
if(users['u2']){
io.sockets.emit('stateok',{});
}
}
});
socket.on('disconn',function(){
socket.emit('disconnection');
})
});
客户端代码:wzq.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>
<script src='https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js'></script>
</head>
<style>
#chess {
display: block;
margin: 50px auto;
box-shadow: -2px -2px 2px #efefef , 5px 5px 5px #b9b9b9;
}
#chess:hover{
cursor: pointer;
}
</style>
<body>
<!-- 棋盘 -->
<input type="radio" name="WZQ" id="black" checked disabled='disabled'>
<label for="black">黑棋</label>
<input type="radio" name="WZQ" id="white" disabled='disabled'>
<label for="white">白棋</label>
<br/>
<input type="button" value="连接服务器" id='conn'>
<input type="button" value="断开服务器" id='disconn'>
<label id='tipMsg'></label>
<!-- <input type="text" name="ip" id="ip" placeholder="请输入IP地址,就像这样(ws://192.168.0.1:3000)"> -->
<canvas id="chess" width="450px" height="450px"></canvas>
<script>
//获取棋盘canvas
var chess = document.getElementById("chess");
//获取2d画布
var context = chess.getContext('2d');
//指定当前是否黑色下,只在UI中使用
var me = true;
if(document.getElementById('white').checked) me=false;
//指定当前位置是否下了棋子,1代表黑,2代表白,0代表空
var curIndex = [];
var dsState = false, isclick = false;
for(var i =0; i <15; i++) {
curIndex[i] = [];
for(var j =0; j <15; j++)
curIndex[i][j] = 0;
}
function drawtable() {
//我们设置棋盘总共15根横线15根总线,左右上下都有15px的边距,其中每个棋子相距30px,因此绘制棋盘从15px开始
for(var i =0; i <15; i++){
for(var j =0; j <15; j++){
//绘制横线
context.moveTo(15, 15 +j *30);
context.lineTo(435, 15 +j *30);
//绘制竖线
context.moveTo(15 +j *30, 15);
context.lineTo(15 +j *30, 435);
//使用灰色描边
context.strokeStyle = "#bfbfbf";
context.stroke();
}
}
};
drawtable();
var socket = io('http://223.2.42.103');
socket.on('connect',function(data){
document.getElementById('tipMsg').innerHTML='<b>等待对方上线。。。</b>';
});
if(me) socket.emit('newUser','u1');
socket.on('tou2',function(data){
//console.log('tou2');
var strArr = data.split('-');
var xx = parseInt(strArr[0]);
var yy = parseInt(strArr[1]);
//开始绘制
context.beginPath();
//绘制指定圆
context.arc(15 +xx *30, 15 +yy *30, 15, 0, 2 *Math.PI);
//进行填充
context.fillStyle = "#636766";
curIndex[xx][yy] = 1;
document.getElementById('tipMsg').innerText='该你下了';
isclick=false;
dsState=true;
context.fill();
//结束绘制
context.closePath();
});
socket.on('tou1',function(data){
//console.log('tou1');
var strArr = data.split('-');
var xx = parseInt(strArr[0]);
var yy = parseInt(strArr[1]);
//开始绘制
context.beginPath();
//绘制指定圆
context.arc(15 +xx *30, 15 +yy *30, 15, 0, 2 *Math.PI);
//进行填充
context.fillStyle = "#b9b9b9";
curIndex[xx][yy] = 2;
document.getElementById('tipMsg').innerText='该你下了';
isclick=false;
dsState=true;
context.fill();
//结束绘制
context.closePath();
});
socket.on('exist',function(data){
me=!me;
document.getElementById('white').checked=true;
document.getElementById('black').checked=false;
socket.emit('newUser','u2');
});
socket.on('stateok',function(data){
document.getElementById('tipMsg').innerHTML='<b>对方已上线,黑棋先下</b>';
if(me){
dsState=true;
isclick=false;
}
});
chess.onclick = function(event) {
if(!dsState||isclick) return;
//获取要下的棋子的位置
var x = Math.floor(event.offsetX /30);
var y = Math.floor(event.offsetY /30);
//判断该点是否已被下了
if(curIndex[x][y] != 0) return;
//开始绘制
context.beginPath();
//绘制指定圆
context.arc(15 +x *30, 15 +y *30, 15, 0, 2 *Math.PI);
//进行填充
if(me) {
context.fillStyle = "#636766";
curIndex[x][y] = 1;
//me = false;
socket.emit('location','u1','u2',x+'-'+y);
}
else {
context.fillStyle = "#b9b9b9";
curIndex[x][y] = 2;
//me = true;
socket.emit('location','u2','u1',x+'-'+y);
}
context.fill();
//结束绘制
context.closePath();
dsState=false;
isclick=true;
if(me){
document.getElementById('tipMsg').innerText='白棋思考中。。。'
}else if(!me){
document.getElementById('tipMsg').innerText='黑棋思考中。。。'
}
};
document.getElementById('conn')
window.unbeforeunload = function(){
socket.emit('disconn');
}
</script>
</body>
</html>
客户端有些代码没有实现,比如说断开连接和手动开启服务器,这些留给读者自己去实现吧,另外判断是否输赢的代码没有写,笔者觉得吧,会玩五子棋的都能看得出来,就不用再写了。