牛骨文教育服务平台(让学习变的简单)
博文笔记

五子棋online---React.js+Socket.io+Node.js

创建时间:2017-01-07 投稿人: 浏览次数:1723

前段时间,在做项目上线前的准备,有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一下,然后根据方法,试着跑跑

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。