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

前段時間,在做項目上線前的準備,有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一下,然後根據方法,試着跑跑

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章