版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_35407267/article/details/54149092
前段时间,在做项目上线前的准备,有bug就改bug,没bug就优化一些性能,自己也有时间胡乱看一些东西。群里都说React火到没朋友,就跟着React的Tutorial敲了一遍,感觉它的组织形式跟之前的jq和ng都不一样,光说不练假把式,就模仿turorial做个五子棋吧,正好朋友们也喜欢玩,就说干就干。
很快单机版的五子棋就完事了,感觉很不爽啊,不切合实际,五子棋明明是对战的嘛。完事了就迅速做成联机对战版的。因为涉及到了实时通讯,在朋友的推荐下了解到了socket.io这个基于websocket的实时通讯工具,非常的nice,跟着它的getting-started走一遍,就能上手了。
其间遇到了通过grunt编译react的问题,记录在http://blog.csdn.net/baidu_35407267/article/details/54173001,界面很简单,jsx代码较长,就贴个主要的component。
//主棋盘
class Board extends React.Component{
constructor() {
super();
this.state = {
'styleArr': Array(225).fill('unit'),//初始化每个坐标
isBlacksTurn:true,//记录此时黑方走棋还是白方走棋
point:-1,//下棋的坐标
urBlack:null,//初始化本玩家的角色,黑方还是白方
online:{}//记录在线人数
};
}
componentWillMount() {
var that = this;
socket.on('role', function(msg){
if(msg.hasOwnProperty('role') && msg.role){
that.setState({urBlack: true,})
console.log('你是黑旗')
}else if(msg.hasOwnProperty('role') && !msg.role){
that.setState({urBlack: false,})
console.log('你是bai旗')
}else{
console.log('人满了,不好意思')
}
})
socket.on('online', function(user){
that.setState({online: user,});
})
}
componentDidMount() {
var that = this;
socket.on('chat message', function(msg){
//更新视图
const styleArray = that.state.styleArr.slice();
styleArray[msg.place] = that.state.isBlacksTurn ? 'unit unit-b' : 'unit unit-w';
that.setState({
'styleArr':styleArray,
isBlacksTurn: !that.state.isBlacksTurn,
point:msg.place,
})
});
socket.on('reset',function(msg){
console.log('reset')
const styleArray = that.state.styleArr.slice();
styleArray.fill('unit')
that.setState({
'styleArr':styleArray,
point:-1,
});
ReactDOM.render(<div></div>,document.getElementById('gameover'));
if(msg.turn){
alert("it's black's turn")
}else{
alert("it's white's turn")
}
})
}
handle(n){
let num=0;
for(let i in this.state.online){
num++;
}
if(num<2){
alert('请等待partner')
return
}
//判断该谁落子
if(this.state.isBlacksTurn==this.state.urBlack){
if(this.state.styleArr[n]!='unit'){//如果落子的地方有子了,就骂他
alert('那有棋子了,你傻啊');
return;
}
socket.emit('chat message',{'place':n,'player':this.state.isBlacksTurn})
}else{
alert('不该你走呢亲')
}
}
reset(){
socket.emit('reset',{"turn":this.state.isBlacksTurn})
}
componentDidUpdate(){
// 更新的时候触发
if(calculateWinner(this.state.styleArr,this.state.point)){
if(this.state.isBlacksTurn!=this.state.urBlack&&this.state.urBlack!=null){
ReactDOM.render(<img src='img/victory.png' className='victory' />,
document.getElementById('gameover'));
}else{
ReactDOM.render(<img src='img/defeat.png' className='victory' />,
document.getElementById('gameover'));
}
}
}
render(){
let board=[];
for(let r=0;r<15;r++){
for(let i=0;i<15;i++){
board[r*15+i]=<Unit key={[r,i]} style={this.state.styleArr[r*15+i]} onClick={() => this.handle(r*15+i)}/>
}
}
return(
<div>
<OnlinePlayer online={this.state.online} />
{board}
<Turn turn={this.state.isBlacksTurn}/>
<Reset onClick={() => this.reset()} />
<div id='gameover'></div>
</div>
)
}
}
后台的node.js比较简单,主要就是一些socket.io的监听和回调也简单的贴一下:
var express=require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.use(express.static('five-in-line'));
var userNum=0;//用来记录在线用户人数
var role=true;//用来分配下棋的身份
var onlineUser={}; //用来存储在线人数及socket的id
io.on('connection', function(socket){
socket.on('login',function(obj){
onlineUser[socket.id]=obj;
//谁来的跟谁分配权限 下黑旗,白旗还是观战
userNum++;
if(userNum==1){
onlineUser[socket.id]=Object.assign(obj,{role:true});
}else if(userNum==2){
onlineUser[socket.id]=Object.assign(obj,{role:false});
}else if(userNum>2){
onlineUser[socket.id]=obj;
}
io.to(socket.id).emit('role', onlineUser[socket.id]);//将身份信息(下黑旗还是白旗)传过去
io.emit('online', onlineUser);//将在线人员名单带过去
console.log(obj.userName,'is loginning');
})
socket.on('disconnect', function(){
console.log(socket.id,'disconnected');
if(onlineUser.hasOwnProperty(socket.id)){//disconnect的时候,将它从onlineUser里删掉
delete onlineUser[socket.id];
}
io.emit('online',onlineUser);//用来同步数据在线人数
userNum--;
});
socket.on('chat message', function(msg){
// 参数为下到什么坐标和目前是黑方or白方
console.log(msg.player?'黑方':'白方','落子在: ' + msg.place);
io.emit('chat message', msg);
});
socket.on('reset', function(msg){
//参数为目前黑旗or白旗
console.log('清除重来');
io.emit('reset',msg);
});
});
http.listen(3000, function(){
console.log('listening on :3000');
});
github地址在https://github.com/guguji5/five-in-line,对实时通讯和react入门感兴趣的可以checkout一下,然后根据方法,试着跑跑