• websocket简单实现五子棋即时对战功能


    几年前做的一个小demo,代码比较老,先上下html显示效果图

    因为代码中注释比较详细,所以就直接上代码了

    html代码,也就是上图展示的效果页面

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title></title>
            <script type="text/javascript" src="../js/jquery-1.12.3.min.js" ></script>
            <script type="text/javascript" src="../js/json2.js" ></script>
            <script type="text/javascript" src="../js/rule.js" ></script>
            <style type="text/css">
                #background{
                    position: relative;
                    margin: 20px auto;
                    /*background: #EAC000;*/
                }
                .chessman{
                    border-radius: 15px;
                    width: 30px;
                    height: 30px;
                    margin: 0 auto;
                }
                .white{
                    background-color:white ;
                }
                .black{
                    background-color: black;
                }
                .grid,.b_grid{
                    float: left;
                }
                .message{
                    width: 320px;
                    height: 100px;
                    margin: 0 auto;
                }
                #messageContent{
                    width: 320px;
                    height: 80px;
                }
            </style>
        </head>
        <body>
            <div id="background">
                <!--<div id="back_grid"></div>-->
                <div id="chess"></div>
            </div>
            <div class="message">
                <textarea id="messageContent" disabled="disabled" readonly="readonly"></textarea>
                <div><input id="message"/> <button onclick="WuZiQi.sendMessage()">发送</button></div>
            </div>
        </body>
    </html>
    chess.html

    接下来是页面rule.js功能代码

    var bout = false;//是否允许落子
    var color = "";//自己落子颜色
    var websocket = null;
    var row = 15;
    var col = 15;
    var widthAndHeight = 30;//格子宽度高度
    var WuZiQi = {
        isEnd:function(xy,chessmanColor){//判断是否结束游戏
            var id = parseInt(xy);
            //竖的计算
            var num = 1;
            num = WuZiQi.shujia(num,id,chessmanColor);
            num = WuZiQi.shujian(num,id,chessmanColor);
            if(num>=5){
                if(chessmanColor==color){
                    confirm("游戏结束!你赢了!");
                }else{
                    confirm("游戏结束!你输了!");
                }
                return ;
            }
            num = 1;
            num = WuZiQi.hengjia(num,id,chessmanColor);
            num = WuZiQi.hengjian(num,id,chessmanColor);
            if(num>=5){
                if(chessmanColor==color){
                    confirm("游戏结束!你赢了!");
                }else{
                    confirm("游戏结束!你输了!");
                }
                return ;
            }
    ;        num = 1;
            num = WuZiQi.zuoxiejia(num,id,chessmanColor);
            num = WuZiQi.zuoxiejian(num,id,chessmanColor);
            if(num>=5){
                if(chessmanColor==color){
                    confirm("游戏结束!你赢了!");
                }else{
                    confirm("游戏结束!你输了!");
                }
                return ;
            }
            num = 1;
            num = WuZiQi.youxiejia(num,id,chessmanColor);
            num = WuZiQi.youxiejian(num,id,chessmanColor);
            if(num>=5){
                if(chessmanColor==color){
                    confirm("游戏结束!你赢了!");
                }else{
                    confirm("游戏结束!你输了!");
                }
                return ;
            }
        },youxiejia:function(num,id,color){
            var yu = id%row;
            id = id+(row-1);
            if(id<(row*col)&&(id%row)<yu){
                var flag = WuZiQi.checkColor(id,color);
                if(flag){
                    num++;
                    return WuZiQi.youxiejia(num,id,color);
                }else{
                    return num;
                }
            }else{
                return num;
            }
        },youxiejian:function(num,id,color){
            var yu = id%row;
            id = id-(row-1);
            if(id>=0&&(id%row)>yu){
                var flag = WuZiQi.checkColor(id,color);
                if(flag){
                    num++;
                    return WuZiQi.youxiejian(num,id,color);
                }else{
                    return num;
                }
            }else{
                return num;
            }
        },zuoxiejia:function(num,id,color){
            var yu = id%row;
            id = id+(row+1);
            if(id<(row*col)&&(id%row)>yu){
                var flag = WuZiQi.checkColor(id,color);
                if(flag){
                    num++;
                    return WuZiQi.zuoxiejia(num,id,color);
                }else{
                    return num;
                }
            }else{
                return num;
            }
        },zuoxiejian:function(num,id,color){
            var yu = id%row;
            id = id-(row+1);
            if(id>=0&&(id%row)<yu){
                var flag = WuZiQi.checkColor(id,color);
                if(flag){
                    num++;
                    return WuZiQi.zuoxiejian(num,id,color);
                }else{
                    return num;
                }
            }else{
                return num;
            }
        },
        hengjia:function(num,id,color){
            var yu = id%row;
            id = id+1;
            if(id<(row*col)&&(id%row)>yu){
                var flag = WuZiQi.checkColor(id,color);
                if(flag){
                    num++;
                    return WuZiQi.hengjia(num,id,color);
                }else{
                    return num;
                }
            }else{
                return num;
            }
            
        },
        hengjian:function(num,id,color){
            var yu = id%row;
            id = id-1;
            if(id>=0&(id%row)<yu){
                var flag = WuZiQi.checkColor(id,color);
                if(flag){
                    num++;
                    return WuZiQi.hengjian(num,id,color);
                }else{
                    return num;
                }
            }else{
                return num;
            }
        },
        shujia:function(num,id,color){
            id = id+row;
            if(id<(row*col)){
                var flag = WuZiQi.checkColor(id,color);
                if(flag){
                    num++;
                    return WuZiQi.shujia(num,id,color);
                }else{
                    return num;
                }
            }else{
                return num;
            }
        },
        shujian:function(num,id,color){
            id = id-row;
            if(id>=0){
                var flag = WuZiQi.checkColor(id,color);
                if(flag){
                    num++;
                    return WuZiQi.shujian(num,id,color);
                }else{
                    return num;
                }
            }else{
                return num;
            }
        },
        checkColor:function(xy,color){
            if($("#"+xy).children("div").hasClass(color)){
                return true;
            }else {
                return false;
            }
        },
        playchess:function(e){
            if(bout&&color!=""){
                if($(e).children("div").length>0){
                    alert("这里已经有子了!请在其它地方落子!");
                    return;
                }
                var result = {};
                result.xy = $(e).attr("id");
                result.color = color;
                result.message = "系统:您已落子,请等待对手落子!";
                result.bout = false;
                if(websocket!=null){
                    websocket.send(JSON.stringify(result));
                }else{
                    $("#messageContent").append("系统:已断开连接");
                    $("#messageContent").append("
    ");
                }
            }else{
                if(color==""){
                    $("#messageContent").append("系统:游戏还没有开始!");
                    $("#messageContent").append("
    ");
                    $("#messageContent").scrollTop($("#messageContent")[0].scrollHeight - $("#messageContent").height());
                }else{
                    $("#messageContent").append("系统:请等待你的对手落子!");
                    $("#messageContent").append("
    ");
                    $("#messageContent").scrollTop($("#messageContent")[0].scrollHeight - $("#messageContent").height());
                }
            }
            
        },
        //发送消息
        sendMessage:function(){
              var message = $("#message").val();
              if(message!=""){
                  var result = {};
                  result.message = message;
                  websocket.send(JSON.stringify(result));
                  $("#message").val("");
              }else{
                  $("#messageContent").append("系统:请不要发送空信息!");
                $("#messageContent").append("
    ");
                $("#messageContent").scrollTop($("#messageContent")[0].scrollHeight - $("#messageContent").height());
              }
              
          }
    };
    $(function(){
        //根据棋盘格子数得到棋盘大小
        $("#background").css({(row*widthAndHeight)+"px",height:(col*widthAndHeight)+"px"});
        //用canvas画棋盘
        var canvas = document.createElement("canvas");
    //    $(canvas).attr({((row-1)*widthAndHeight)+"px",height:(col-1)*widthAndHeight+"px"});
    //    $(canvas).css({"position":"relative","top":(widthAndHeight/2)+"px","left":(widthAndHeight/2)+"px","z-index":9999});
        $(canvas).attr({(row*widthAndHeight)+"px",height:col*widthAndHeight+"px"});
        $(canvas).css({position:"relative","z-index":9999});
        var cot = canvas.getContext("2d");
        cot.fillStyle = "#EAC000";
        cot.fillRect(0,0,row*widthAndHeight,col*widthAndHeight);
        cot.lineWidth = 1;
        var offset = widthAndHeight/2;
        for(var i=0;i<row;i++){//面板大小和棋盘一致,但格子线条比棋盘的行列少1
            cot.moveTo((widthAndHeight*i)+offset,0+offset);
            cot.lineTo((widthAndHeight*i)+offset,(col*widthAndHeight)-offset);
        }
        for(var j=0;j<col;j++){
            cot.moveTo(0+offset,(widthAndHeight*j)+offset);
            cot.lineTo((widthAndHeight*row)-offset,(j*widthAndHeight)+offset);
        }    
        cot.stroke();
        $("#background").prepend(canvas);
        //生成格子横线
    //    var b_str="";
    //    for(var i=0;i<(row-1);i++){
    //        for(var j=0;j<(col-1);j++){
    //            b_str+="<div class='b_grid'></div>";
    //        }
    //    }
    //    $("#back_grid").append(b_str);
    //    $("#back_grid").css({((row-1)*widthAndHeight)+"px",height:(col-1)*widthAndHeight+"px",position: "absolute",top:(widthAndHeight/2)+"px",left:(widthAndHeight/2)+"px",border:"solid 1px black"});
    //    //减去线的宽度
    //    $(".b_grid").css({(widthAndHeight-2)+"px",height:(widthAndHeight-2)+"px",border:"solid 1px black"});
        //生成落子格子
        var str="";
        var index = 0;
        for(var i=0;i<row;i++){
            for(var j=0;j<col;j++){
                str+="<div class='grid' id=""+index+""></div>";
                index++;
            }
        }
        $("#chess").empty();
        $("#chess").append(str);
        $("#chess").css({(row*widthAndHeight)+"px",height:(col*widthAndHeight)+"px",position: "absolute",top:"0px",left:"0px","z-index":99999});
        $(".grid").on("click",function(){
            WuZiQi.playchess(this);
        });
        $(".grid").css({widthAndHeight+"px",height:widthAndHeight+"px"});
        
        
          //判断当前浏览器是否支持WebSocket
          if('WebSocket' in window){
              websocket = new WebSocket("ws://"+window.location.host+"/WuZiQi/wuziqisocket");
          }
          else{
              alert('Not support websocket');
          }
           
          //连接发生错误的回调方法
          websocket.onerror = function(){
              
          };
           
          //连接成功建立的回调方法
          websocket.onopen = function(event){
              
          };
           
          //接收到消息的回调方法(包含了聊天,落子,开始游戏)
          websocket.onmessage = function(){
              var result = JSON.parse(event.data);
            if(result.message!=""){
                $("#messageContent").append(result.message);
                $("#messageContent").append("
    ");
                //将多行文本滚动总是在最下方
                $("#messageContent").scrollTop($("#messageContent")[0].scrollHeight - $("#messageContent").height());
            }
            if(result.xy!=""&&result.color!=""){
                $("#"+result.xy).html("<div class="chessman "+result.color+""></div>");
                bout = result.bout;//落子后才改状态
                WuZiQi.isEnd(result.xy,result.color);
            }else if(result.xy==""&&result.bout){//没有坐标且bout为true,则为对局首次开始落子
                bout = result.bout;
            }
                
            if(result.xy==""&&result.color!=""){//没有坐标,但有颜色,则为首次赋予棋子颜色
                color = result.color;
            }
          };
           
          //连接关闭的回调方法
          websocket.onclose = function(){
    
          };
           
          //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
          window.onbeforeunload = function(){
              websocket.close();
          };
           
           
          //关闭连接
          function closeWebSocket(){
              websocket.close();
          }
    });
    rule.js

    java封装用来传输信息的对象代码

    package com.weguard.websocket;
    
    /**
     * 
     * @author xuhan
     *
     */
    public class Result {
        /**
         * 落子坐标
         */
        private String xy;
        /**
         * 发送消息
         */
        private String message;
        /**
         * 是否允许落子
         */
        private boolean bout;
        /**
         * 落子颜色
         */
        private String color;
        public String getXy() {
            return xy;
        }
        public void setXy(String xy) {
            this.xy = xy;
        }
        public String getMessage() {
            return message;
        }
        public void setMessage(String message) {
            this.message = message;
        }
        public boolean isBout() {
            return bout;
        }
        public void setBout(boolean bout) {
            this.bout = bout;
        }
        public String getColor() {
            return color;
        }
        public void setColor(String color) {
            this.color = color;
        }
        
        
    }
    Result.java

    最后是WebSocket的代码

    package com.weguard.websocket;
    
    import java.io.IOException;
    import java.util.HashMap;
    
    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    
    import net.sf.json.JSONObject;
    
    //该注解用来指定一个URI,客户端可以通过这个URI来连接到WebSocket。类似Servlet的注解mapping。无需在web.xml中配置。
    @ServerEndpoint(value="/wuziqisocket") 
    public class WebSocket {
      //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
      private static HashMap<String,WebSocket> webSocketMap = new HashMap<String,WebSocket>();
      //与某个客户端的连接会话,需要通过它来给客户端发送数据
      private Session session;
      //连上来的页面序号,用来配对对战,1与2一组,3与4一组,依次类推,奇数为黑先走,偶数为白,后走
      private static int index = 0;
      //同上,用来从hashMap中获取websocket,(我也忘记当时为啥要另外用一个mykey了,而不是直接用index来获取)
      private int mykey = 0;
       
      /**
       * 连接建立成功调用的方法
       * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
     * @throws IOException 
       */
      @OnOpen
      public void onOpen( Session session){
          this.session = session;
          index++;
          try {
              Result result = new Result();
              if(index%2==0){
                  WebSocket socket1 = webSocketMap.get((index-1)+"");
                  if(socket1!=null){
                      result.setBout(true);
                      result.setMessage("系统:游戏开始,请您先落子!");
                      result.setColor("black");
                      JSONObject json1 = JSONObject.fromObject(result);
                      socket1.sendMessage(json1.toString());
                      //对先落子的对象发送数据结束
                      result.setMessage("系统:游戏开始,请等待对手落子!");
                      result.setBout(false);
                      result.setColor("white");
                      this.sendMessage(JSONObject.fromObject(result).toString());
                      //对后出手的发送消息结束
                  }else{//偶数时没有查询到与之对应的对手,则其变为奇数,成为等待匹配的人
                      index--;
                      result.setMessage("系统:等待玩家匹配!");
                      this.sendMessage(JSONObject.fromObject(result).toString());
                  }
              }else{
                  result.setMessage("系统:等待玩家匹配!");
                  this.sendMessage(JSONObject.fromObject(result).toString());
              }
              this.mykey = index;
              webSocketMap.put(mykey+"", this);     //加入map中
              System.out.println(webSocketMap.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
      }
       
      /**
       * 连接关闭调用的方法
     * @throws IOException 
       */
      @OnClose
      public void onClose(){
          webSocketMap.remove(mykey+"");  //从set中删除
          try {
              WebSocket socket = null;
              if(mykey%2==0){
                  socket = webSocketMap.get((mykey-1)+"");
              }else{
                  socket = webSocketMap.get((mykey+1)+"");
              }
              if(socket!=null){
                  Result result = new Result();
                  result.setMessage("你的对手已离开!");
                  socket.sendMessage(JSONObject.fromObject(result).toString());
              }
        } catch (Exception e) {
            e.printStackTrace();
        }
      }
      /**
       * 收到客户端消息后调用的方法
       * @param message 客户端发送过来的消息
       * @param session 可选的参数
       */
      @OnMessage
      public void onMessage(String message) {
          System.out.println(message);
          JSONObject json = JSONObject.fromObject(message);
          Result result = (Result) JSONObject.toBean(json,Result.class);
          try {
              WebSocket socket = null;
              if(mykey%2==0){
                  socket = webSocketMap.get((mykey-1)+"");
              }else{
                  socket = webSocketMap.get((mykey+1)+"");
              }
              if(socket!=null){
                  if(result.getXy()!=null&&!"".equals(result.getXy())){//有坐标表示为落子,反之则为发送信息
                      this.sendMessage(message);
                      result.setBout(true);//对手的bout改为true,表示接下来可以落子
                      result.setMessage("系统:对方已落子,正在等待您落子!");
                      socket.sendMessage(JSONObject.fromObject(result).toString());
                  }else{//没有坐标表示为单纯的聊天
                      Result newResult = new Result();
                      newResult.setMessage("自己:"+result.getMessage());
                      this.sendMessage(JSONObject.fromObject(newResult).toString());
                      newResult.setMessage("对方:"+result.getMessage());
                      socket.sendMessage(JSONObject.fromObject(newResult).toString());
                  }
              }
              
              
        } catch (Exception e) {
            e.printStackTrace();
        }
      }
       
      /**
       * 发生错误时调用
       * @param session
       * @param error
       */
      @OnError
      public void onError(Session session, Throwable error){
          System.out.println("连接断开");
    //      error.printStackTrace();
      }
      /**
       * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
       * @param message
       * @throws IOException
       */
      public void sendMessage(String message) throws IOException{
          this.session.getBasicRemote().sendText(message);
          //this.session.getAsyncRemote().sendText(message);
      }
    }
    WebSocket.java

    只需要上面的4个代码,当然jquery,json2这些依然还是需要的,同学们新建一个

  • 相关阅读:
    20201208史逸霏第六章学习笔记
    第三章笔记
    实现ls
    mystat
    改进ls
    第十章笔记
    cat userlist
    第七、八章笔记
    mypwd
    类成员函数指针写入map里怎么才能调用它呢?转载
  • 原文地址:https://www.cnblogs.com/x-h-s/p/9406663.html
Copyright © 2020-2023  润新知