几年前做的一个小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>
接下来是页面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("\n"); } }else{ if(color==""){ $("#messageContent").append("系统:游戏还没有开始!"); $("#messageContent").append("\n"); $("#messageContent").scrollTop($("#messageContent")[0].scrollHeight - $("#messageContent").height()); }else{ $("#messageContent").append("系统:请等待你的对手落子!"); $("#messageContent").append("\n"); $("#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("\n"); $("#messageContent").scrollTop($("#messageContent")[0].scrollHeight - $("#messageContent").height()); } } }; $(function(){ //根据棋盘格子数得到棋盘大小 $("#background").css({width:(row*widthAndHeight)+"px",height:(col*widthAndHeight)+"px"}); //用canvas画棋盘 var canvas = document.createElement("canvas"); // $(canvas).attr({width:((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({width:(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({width:((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({width:(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({width:(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({width: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("\n"); //将多行文本滚动总是在最下方 $("#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(); } });
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; } }
最后是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); } }
只需要上面的4个代码,当然jquery,json2这些依然还是需要的,同学们新建一个